@@ -23,6 +23,19 @@ const REGEXP_CONTENTHASH = /\[contenthash(?::(\d+))?\]/i;
23
23
const REGEXP_NAME = / \[ n a m e \] / i;
24
24
const DEFAULT_FILENAME = '[name].css' ;
25
25
26
+ const compareIds = ( a , b ) => {
27
+ if ( typeof a !== typeof b ) {
28
+ return typeof a < typeof b ? - 1 : 1 ;
29
+ }
30
+ if ( a < b ) return - 1 ;
31
+ if ( a > b ) return 1 ;
32
+ return 0 ;
33
+ } ;
34
+
35
+ const compareModulesByIdentifier = ( a , b ) => {
36
+ return compareIds ( a . identifier ( ) , b . identifier ( ) ) ;
37
+ } ;
38
+
26
39
class CssDependencyTemplate {
27
40
apply ( ) { }
28
41
}
@@ -82,8 +95,8 @@ class CssModule extends webpack.Module {
82
95
callback ( ) ;
83
96
}
84
97
85
- updateHash ( hash ) {
86
- super . updateHash ( hash ) ;
98
+ updateHash ( hash , chunkGraph ) {
99
+ super . updateHash ( hash , chunkGraph ) ;
87
100
88
101
hash . update ( this . content ) ;
89
102
hash . update ( this . media || '' ) ;
@@ -132,7 +145,7 @@ class MiniCssExtractPlugin {
132
145
) ;
133
146
}
134
147
} else {
135
- this . options . chunkFilename = '[id].css' ;
148
+ this . options . chunkFilename = DEFAULT_FILENAME ;
136
149
}
137
150
}
138
151
}
@@ -149,71 +162,117 @@ class MiniCssExtractPlugin {
149
162
new CssDependencyTemplate ( )
150
163
) ;
151
164
152
- compilation . mainTemplate . hooks . renderManifest . tap (
153
- pluginName ,
154
- ( result , { chunk } ) => {
155
- const renderedModules = Array . from ( chunk . modulesIterable ) . filter (
156
- ( module ) => module . type === MODULE_TYPE
157
- ) ;
158
-
159
- const filenameTemplate =
160
- chunk . filenameTemplate || this . options . filename ;
161
-
162
- if ( renderedModules . length > 0 ) {
163
- result . push ( {
164
- render : ( ) =>
165
- this . renderContentAsset (
166
- compilation ,
165
+ // Webpack 4
166
+ if ( ! compilation . hooks . renderManifest ) {
167
+ compilation . mainTemplate . hooks . renderManifest . tap (
168
+ pluginName ,
169
+ ( result , { chunk } ) => {
170
+ const { chunkGraph } = compilation ;
171
+
172
+ const renderedModules = Array . from (
173
+ this . getChunks ( chunk , chunkGraph )
174
+ ) . filter ( ( module ) => module . type === MODULE_TYPE ) ;
175
+
176
+ const filenameTemplate =
177
+ chunk . filenameTemplate || this . options . filename ;
178
+
179
+ if ( renderedModules . length > 0 ) {
180
+ result . push ( {
181
+ render : ( ) =>
182
+ this . renderContentAsset (
183
+ compilation ,
184
+ chunk ,
185
+ renderedModules ,
186
+ compilation . runtimeTemplate . requestShortener
187
+ ) ,
188
+ filenameTemplate,
189
+ pathOptions : {
167
190
chunk,
168
- renderedModules ,
169
- compilation . runtimeTemplate . requestShortener
170
- ) ,
171
- filenameTemplate,
172
- pathOptions : {
173
- chunk,
174
- contentHashType : MODULE_TYPE ,
175
- } ,
176
- identifier : `${ pluginName } .${ chunk . id } ` ,
177
- hash : chunk . contentHash [ MODULE_TYPE ] ,
178
- } ) ;
191
+ contentHashType : MODULE_TYPE ,
192
+ } ,
193
+ identifier : `${ pluginName } .${ chunk . id } ` ,
194
+ hash : chunk . contentHash [ MODULE_TYPE ] ,
195
+ } ) ;
196
+ }
179
197
}
180
- }
181
- ) ;
182
-
183
- compilation . chunkTemplate . hooks . renderManifest . tap (
184
- pluginName ,
185
- ( result , { chunk } ) => {
186
- const renderedModules = Array . from ( chunk . modulesIterable ) . filter (
187
- ( module ) => module . type === MODULE_TYPE
188
- ) ;
189
-
190
- const filenameTemplate =
191
- chunk . filenameTemplate || this . options . chunkFilename ;
192
-
193
- if ( renderedModules . length > 0 ) {
194
- result . push ( {
195
- render : ( ) =>
196
- this . renderContentAsset (
197
- compilation ,
198
+ ) ;
199
+
200
+ compilation . chunkTemplate . hooks . renderManifest . tap (
201
+ pluginName ,
202
+ ( result , { chunk } ) => {
203
+ const { chunkGraph } = compilation ;
204
+
205
+ const renderedModules = Array . from (
206
+ this . getChunks ( chunk , chunkGraph )
207
+ ) . filter ( ( module ) => module . type === MODULE_TYPE ) ;
208
+
209
+ const filenameTemplate =
210
+ chunk . filenameTemplate || this . options . chunkFilename ;
211
+
212
+ if ( renderedModules . length > 0 ) {
213
+ result . push ( {
214
+ render : ( ) =>
215
+ this . renderContentAsset (
216
+ compilation ,
217
+ chunk ,
218
+ renderedModules ,
219
+ compilation . runtimeTemplate . requestShortener
220
+ ) ,
221
+ filenameTemplate,
222
+ pathOptions : {
198
223
chunk,
199
- renderedModules ,
200
- compilation . runtimeTemplate . requestShortener
201
- ) ,
202
- filenameTemplate,
203
- pathOptions : {
204
- chunk,
205
- contentHashType : MODULE_TYPE ,
206
- } ,
207
- identifier : `${ pluginName } .${ chunk . id } ` ,
208
- hash : chunk . contentHash [ MODULE_TYPE ] ,
209
- } ) ;
224
+ contentHashType : MODULE_TYPE ,
225
+ } ,
226
+ identifier : `${ pluginName } .${ chunk . id } ` ,
227
+ hash : chunk . contentHash [ MODULE_TYPE ] ,
228
+ } ) ;
229
+ }
210
230
}
211
- }
212
- ) ;
231
+ ) ;
232
+ } else {
233
+ compilation . hooks . renderManifest . tap (
234
+ pluginName ,
235
+ ( result , { chunk } ) => {
236
+ const { chunkGraph } = compilation ;
237
+
238
+ const renderedModules = Array . from (
239
+ this . getChunks ( chunk , chunkGraph )
240
+ ) . filter ( ( module ) => module . type === MODULE_TYPE ) ;
241
+
242
+ const filenameTemplate =
243
+ chunk . filenameTemplate || chunk . hasRuntime ( )
244
+ ? this . options . filename
245
+ : this . options . chunkFilename ;
246
+
247
+ if ( renderedModules . length > 0 ) {
248
+ result . push ( {
249
+ render : ( ) =>
250
+ this . renderContentAsset (
251
+ compilation ,
252
+ chunk ,
253
+ renderedModules ,
254
+ compilation . runtimeTemplate . requestShortener
255
+ ) ,
256
+ filenameTemplate,
257
+ pathOptions : {
258
+ chunk,
259
+ contentHashType : MODULE_TYPE ,
260
+ } ,
261
+ identifier : `${ pluginName } .${ chunk . id } ` ,
262
+ hash : chunk . contentHash [ MODULE_TYPE ] ,
263
+ } ) ;
264
+ }
265
+ }
266
+ ) ;
267
+ }
213
268
214
- compilation . mainTemplate . hooks . hashForChunk . tap (
215
- pluginName ,
216
- ( hash , chunk ) => {
269
+ if (
270
+ typeof webpack . javascript !== 'undefined' &&
271
+ typeof webpack . javascript . JavascriptModulesPlugin !== 'undefined'
272
+ ) {
273
+ webpack . javascript . JavascriptModulesPlugin . getCompilationHooks (
274
+ compilation
275
+ ) . chunkHash . tap ( pluginName , ( chunk , hash ) => {
217
276
const { chunkFilename } = this . options ;
218
277
219
278
if ( REGEXP_CHUNKHASH . test ( chunkFilename ) ) {
@@ -231,17 +290,40 @@ class MiniCssExtractPlugin {
231
290
if ( REGEXP_NAME . test ( chunkFilename ) ) {
232
291
hash . update ( JSON . stringify ( chunk . getChunkMaps ( true ) . name ) ) ;
233
292
}
234
- }
235
- ) ;
293
+ } ) ;
294
+ } else {
295
+ compilation . mainTemplate . hooks . hashForChunk . tap (
296
+ pluginName ,
297
+ ( hash , chunk ) => {
298
+ const { chunkFilename } = this . options ;
299
+
300
+ if ( REGEXP_CHUNKHASH . test ( chunkFilename ) ) {
301
+ hash . update ( JSON . stringify ( chunk . getChunkMaps ( true ) . hash ) ) ;
302
+ }
303
+
304
+ if ( REGEXP_CONTENTHASH . test ( chunkFilename ) ) {
305
+ hash . update (
306
+ JSON . stringify (
307
+ chunk . getChunkMaps ( true ) . contentHash [ MODULE_TYPE ] || { }
308
+ )
309
+ ) ;
310
+ }
311
+
312
+ if ( REGEXP_NAME . test ( chunkFilename ) ) {
313
+ hash . update ( JSON . stringify ( chunk . getChunkMaps ( true ) . name ) ) ;
314
+ }
315
+ }
316
+ ) ;
317
+ }
236
318
237
319
compilation . hooks . contentHash . tap ( pluginName , ( chunk ) => {
238
- const { outputOptions } = compilation ;
320
+ const { outputOptions, chunkGraph } = compilation ;
239
321
const { hashFunction, hashDigest, hashDigestLength } = outputOptions ;
240
322
const hash = createHash ( hashFunction ) ;
241
323
242
- for ( const m of chunk . modulesIterable ) {
324
+ for ( const m of this . getChunks ( chunk , chunkGraph ) ) {
243
325
if ( m . type === MODULE_TYPE ) {
244
- m . updateHash ( hash ) ;
326
+ m . updateHash ( hash , chunkGraph ) ;
245
327
}
246
328
}
247
329
@@ -255,7 +337,7 @@ class MiniCssExtractPlugin {
255
337
const { mainTemplate } = compilation ;
256
338
257
339
mainTemplate . hooks . localVars . tap ( pluginName , ( source , chunk ) => {
258
- const chunkMap = this . getCssChunkObject ( chunk ) ;
340
+ const chunkMap = this . getCssChunkObject ( chunk , compilation ) ;
259
341
260
342
if ( Object . keys ( chunkMap ) . length > 0 ) {
261
343
return Template . asString ( [
@@ -276,17 +358,28 @@ class MiniCssExtractPlugin {
276
358
mainTemplate . hooks . requireEnsure . tap (
277
359
pluginName ,
278
360
( source , chunk , hash ) => {
279
- const chunkMap = this . getCssChunkObject ( chunk ) ;
361
+ const chunkMap = this . getCssChunkObject ( chunk , compilation ) ;
362
+ const isWebpackNext = typeof webpack . RuntimeGlobals !== 'undefined' ;
280
363
281
364
if ( Object . keys ( chunkMap ) . length > 0 ) {
365
+ const maintemplateObject = isWebpackNext
366
+ ? compilation
367
+ : mainTemplate ;
282
368
const chunkMaps = chunk . getChunkMaps ( ) ;
283
- const { crossOriginLoading } = mainTemplate . outputOptions ;
284
- const linkHrefPath = mainTemplate . getAssetPath (
369
+ const { crossOriginLoading } = maintemplateObject . outputOptions ;
370
+ const linkHrefPath = maintemplateObject . getAssetPath (
285
371
JSON . stringify ( this . options . chunkFilename ) ,
286
372
{
287
- hash : `" + ${ mainTemplate . renderCurrentHashCode ( hash ) } + "` ,
373
+ hash : isWebpackNext
374
+ ? `" + ${ webpack . RuntimeGlobals . getFullHash } + "`
375
+ : `" + ${ mainTemplate . renderCurrentHashCode ( hash ) } + "` ,
288
376
hashWithLength : ( length ) =>
289
- `" + ${ mainTemplate . renderCurrentHashCode ( hash , length ) } + "` ,
377
+ isWebpackNext
378
+ ? `" + ${ webpack . RuntimeGlobals . getFullHash } + "`
379
+ : `" + ${ mainTemplate . renderCurrentHashCode (
380
+ hash ,
381
+ length
382
+ ) } + "`,
290
383
chunk : {
291
384
id : '" + chunkId + "' ,
292
385
hash : `" + ${ JSON . stringify ( chunkMaps . hash ) } [chunkId] + "` ,
@@ -347,7 +440,11 @@ class MiniCssExtractPlugin {
347
440
'promises.push(installedCssChunks[chunkId] = new Promise(function(resolve, reject) {' ,
348
441
Template . indent ( [
349
442
`var href = ${ linkHrefPath } ;` ,
350
- `var fullhref = ${ mainTemplate . requireFn } .p + href;` ,
443
+ `var fullhref = ${
444
+ isWebpackNext
445
+ ? '__webpack_require__'
446
+ : mainTemplate . requireFn
447
+ } .p + href;`,
351
448
'var existingLinkTags = document.getElementsByTagName("link");' ,
352
449
'for(var i = 0; i < existingLinkTags.length; i++) {' ,
353
450
Template . indent ( [
@@ -408,11 +505,21 @@ class MiniCssExtractPlugin {
408
505
} ) ;
409
506
}
410
507
411
- getCssChunkObject ( mainChunk ) {
508
+ getChunks ( chunk , chunkGraph ) {
509
+ return typeof chunkGraph !== 'undefined'
510
+ ? chunkGraph . getOrderedChunkModulesIterable (
511
+ chunk ,
512
+ compareModulesByIdentifier
513
+ )
514
+ : chunk . modulesIterable ;
515
+ }
516
+
517
+ getCssChunkObject ( mainChunk , compilation ) {
412
518
const obj = { } ;
519
+ const { chunkGraph } = compilation ;
413
520
414
521
for ( const chunk of mainChunk . getAllAsyncChunks ( ) ) {
415
- for ( const module of chunk . modulesIterable ) {
522
+ for ( const module of this . getChunks ( chunk , chunkGraph ) ) {
416
523
if ( module . type === MODULE_TYPE ) {
417
524
obj [ chunk . id ] = 1 ;
418
525
break ;
@@ -427,8 +534,12 @@ class MiniCssExtractPlugin {
427
534
let usedModules ;
428
535
429
536
const [ chunkGroup ] = chunk . groupsIterable ;
537
+ const moduleIndexFunctionName =
538
+ typeof compilation . chunkGraph !== 'undefined'
539
+ ? 'getModulePostOrderIndex'
540
+ : 'getModuleIndex2' ;
430
541
431
- if ( typeof chunkGroup . getModuleIndex2 === 'function' ) {
542
+ if ( typeof chunkGroup [ moduleIndexFunctionName ] === 'function' ) {
432
543
// Store dependencies for modules
433
544
const moduleDependencies = new Map ( modules . map ( ( m ) => [ m , new Set ( ) ] ) ) ;
434
545
const moduleDependenciesReasons = new Map (
@@ -443,7 +554,7 @@ class MiniCssExtractPlugin {
443
554
. map ( ( m ) => {
444
555
return {
445
556
module : m ,
446
- index : cg . getModuleIndex2 ( m ) ,
557
+ index : cg [ moduleIndexFunctionName ] ( m ) ,
447
558
} ;
448
559
} )
449
560
// eslint-disable-next-line no-undefined
0 commit comments