@@ -27,13 +27,17 @@ class Integrity {
2727
2828 this . options = options ;
2929 this . chunkChildChunksMap = new WeakMap ( ) ;
30- this . referencePlaceholders = new Map ( ) ;
31- this . placeholderByChunkId = new Map ( ) ;
3230 this . chunkByChunkId = new Map ( ) ;
31+ this . templateByChunkId = new Map ( ) ;
32+ this . placeholderByChunkId = new Map ( ) ;
33+ this . Template = null ;
3334 }
3435
3536 apply ( compiler ) {
3637 const { pluginName } = this ;
38+ const { Template } = compiler . webpack ;
39+
40+ this . Template = Template ;
3741
3842 compiler . hooks . afterPlugins . tap ( pluginName , ( compiler ) => {
3943 compiler . hooks . thisCompilation . tap ( { name : pluginName , stage : - 10000 } , ( compilation ) => {
@@ -69,12 +73,12 @@ class Integrity {
6973 this . isRealContentHash = this . options . isRealContentHash ( ) ;
7074
7175 // dynamically import a JS file
72- mainTemplate . hooks . jsonpScript . tap ( pluginName , ( source ) => this . addReference ( 'script' , source ) ) ;
73- mainTemplate . hooks . linkPreload . tap ( pluginName , ( source ) => this . addReference ( 'link' , source ) ) ;
74- mainTemplate . hooks . localVars . tap ( pluginName , this . setReferencePlaceholder . bind ( this ) ) ;
76+ mainTemplate . hooks . jsonpScript . tap ( pluginName , ( source ) => this . getTemplateByTag ( 'script' , source ) ) ;
77+ mainTemplate . hooks . linkPreload . tap ( pluginName , ( source ) => this . getTemplateByTag ( 'link' , source ) ) ;
78+ mainTemplate . hooks . localVars . tap ( pluginName , this . getTemplateByChunk . bind ( this ) ) ;
7579
7680 compilation . hooks . beforeRuntimeRequirements . tap ( pluginName , ( ) => {
77- this . placeholderByChunkId . clear ( ) ;
81+ this . templateByChunkId . clear ( ) ;
7882 } ) ;
7983
8084 compilation . hooks . processAssets . tap (
@@ -111,6 +115,9 @@ class Integrity {
111115 return chunk ? Integrity . getIntegrity ( this . compilation , content [ 0 ] , chunk ) : undefined ;
112116 }
113117
118+ /**
119+ * @param {Object } assets
120+ */
114121 processAssets ( assets ) {
115122 const { compilation, isRealContentHash } = this ;
116123 const { compiler } = compilation ;
@@ -122,18 +129,15 @@ class Integrity {
122129 continue ;
123130 }
124131
125- let childChunks = this . chunkChildChunksMap . get ( chunk ) ;
126- if ( ! childChunks ) {
127- childChunks = chunk . getAllAsyncChunks ( ) ;
128- this . chunkChildChunksMap . set ( chunk , childChunks ) ;
129- }
132+ const childChunks = this . getChildChunks ( chunk ) ;
130133
131134 for ( const childChunk of childChunks ) {
132135 if ( childChunk . id == null ) {
133136 continue ;
134137 }
135138
136139 // TODO: find the use case when childChunk.files.size > 1
140+ // the size of childChunk.files is always 1
137141 const childChunkFile = [ ...childChunk . files ] [ 0 ] ;
138142 const placeholder = this . placeholderByChunkId . get ( childChunk . id ) ;
139143
@@ -143,16 +147,22 @@ class Integrity {
143147 childChunkFile ,
144148 ( source ) => source ,
145149 ( assetInfo ) => {
146- return assetInfo
147- ? {
148- ...assetInfo ,
149- contenthash : Array . isArray ( assetInfo . contenthash )
150- ? [ ...new Set ( [ ...assetInfo . contenthash , placeholder ] ) ]
151- : assetInfo . contenthash
152- ? [ ...new Set ( [ assetInfo . contenthash , placeholder ] ) ]
153- : placeholder ,
154- }
155- : undefined ;
150+ if ( ! assetInfo ) {
151+ return undefined ;
152+ }
153+
154+ let contenthash = placeholder ;
155+
156+ if ( Array . isArray ( assetInfo . contenthash ) ) {
157+ contenthash = [ ...new Set ( [ ...assetInfo . contenthash , placeholder ] ) ] ;
158+ } else if ( assetInfo . contenthash ) {
159+ contenthash = [ ...new Set ( [ assetInfo . contenthash , placeholder ] ) ] ;
160+ }
161+
162+ return {
163+ ...assetInfo ,
164+ contenthash,
165+ } ;
156166 }
157167 ) ;
158168 } else {
@@ -172,13 +182,28 @@ class Integrity {
172182 }
173183
174184 /**
175- * Add the reference of integrity hashes into a tag object.
185+ * @param {Chunk } chunk The webpack chunk.
186+ * @return {Set<Chunk> } The child chunks.
187+ */
188+ getChildChunks ( chunk ) {
189+ let childChunks = this . chunkChildChunksMap . get ( chunk ) ;
190+
191+ if ( ! childChunks ) {
192+ childChunks = chunk . getAllAsyncChunks ( ) ;
193+ this . chunkChildChunksMap . set ( chunk , childChunks ) ;
194+ }
195+
196+ return childChunks ;
197+ }
198+
199+ /**
200+ * Create the integrity template by the tag.
176201 *
177202 * @param {string } tagName
178203 * @param {string } source
179204 * @return {string }
180205 */
181- addReference = ( tagName , source ) => {
206+ getTemplateByTag = ( tagName , source ) => {
182207 const { compilation, pluginName } = this ;
183208 const { Template } = compilation . compiler . webpack ;
184209 const { crossOriginLoading } = compilation . outputOptions ;
@@ -191,40 +216,42 @@ class Integrity {
191216 } ;
192217
193218 /**
194- * Set the placeholder in the hash reference using the hash of a chunk file.
219+ * Create the integrity template by the chunk.
220+ *
221+ * Saves the placeholder in the hash reference using the hash of a chunk file.
195222 * When the asset is processed, the placeholder will be replaced
196223 * with real integrity hash of the processed asset.
197224 *
198225 * @param {string } source
199226 * @param {Chunk } chunk
200227 * @return {string }
201228 */
202- setReferencePlaceholder ( source , chunk ) {
203- const { Template } = this . compilation . compiler . webpack ;
204-
205- if ( this . referencePlaceholders . has ( chunk . id ) ) {
206- return this . referencePlaceholders . get ( chunk . id ) ;
229+ getTemplateByChunk ( source , chunk ) {
230+ if ( this . templateByChunkId . has ( chunk . id ) ) {
231+ return this . templateByChunkId . get ( chunk . id ) ;
207232 }
208233
209- const childChunks = chunk . getAllAsyncChunks ( ) ;
210- this . chunkChildChunksMap . set ( chunk , childChunks ) ;
234+ const childChunks = this . getChildChunks ( chunk ) ;
235+
236+ if ( childChunks . size < 1 ) {
237+ return source ;
238+ }
211239
212240 const placeholders = { } ;
213241 for ( const childChunk of childChunks ) {
214- const placeholder = getPlaceholder ( childChunk . id ) ;
242+ let placeholder = this . placeholderByChunkId . get ( childChunk . id ) ;
243+ if ( ! placeholder ) {
244+ placeholder = getPlaceholder ( childChunk . id ) ;
245+ this . placeholderByChunkId . set ( childChunk . id , placeholder ) ;
246+ }
215247 placeholders [ childChunk . id ] = placeholder ;
216- this . placeholderByChunkId . set ( childChunk . id , placeholder ) ;
217248 this . chunkByChunkId . set ( childChunk . id , childChunk ) ;
218249 }
219250
220- if ( Object . keys ( placeholders ) . length > 0 ) {
221- const refTemplate = Template . asString ( [ source , `${ hashesReference } = ${ JSON . stringify ( placeholders ) } ;` ] ) ;
222- this . referencePlaceholders . set ( chunk . id , refTemplate ) ;
223-
224- return refTemplate ;
225- }
251+ const template = this . Template . asString ( [ source , `${ hashesReference } = ${ JSON . stringify ( placeholders ) } ;` ] ) ;
252+ this . templateByChunkId . set ( chunk . id , template ) ;
226253
227- return source ;
254+ return template ;
228255 }
229256
230257 /**
@@ -320,10 +347,10 @@ class Integrity {
320347 */
321348const getPlaceholder = ( chunkId ) => {
322349 // the prefix must be exact 7 chars, the same length as a hash function name, e.g. 'sha256-'
323- const placeholderPrefix = '___TMP -' ;
350+ const prefix = 'xxxxxx -' ;
324351 const hash = Integrity . computeIntegrity ( chunkId ) ;
325352
326- return placeholderPrefix + hash . slice ( placeholderPrefix . length ) ;
353+ return prefix + hash . slice ( prefix . length ) ;
327354} ;
328355
329356module . exports = Integrity ;
0 commit comments