@@ -12,6 +12,7 @@ const {
12
12
util : { createHash } ,
13
13
} = webpack
14
14
15
+ const isWebpack5 = parseInt ( webpack . version ) === 5
15
16
const MODULE_TYPE = 'css/mini-extract'
16
17
17
18
const pluginName = 'mini-css-extract-plugin'
@@ -22,6 +23,14 @@ const REGEXP_NAME = /\[name\]/i
22
23
const REGEXP_PLACEHOLDERS = / \[ ( n a m e | i d | c h u n k h a s h ) \] / g
23
24
const DEFAULT_FILENAME = '[name].css'
24
25
26
+ function getModulesIterable ( compilation , chunk ) {
27
+ if ( isWebpack5 ) {
28
+ return compilation . chunkGraph . getChunkModulesIterable ( chunk )
29
+ }
30
+
31
+ return chunk . modulesIterable
32
+ }
33
+
25
34
class CssDependencyTemplate {
26
35
apply ( ) { }
27
36
}
@@ -68,94 +77,103 @@ class MiniCssExtractPlugin {
68
77
new CssDependencyTemplate ( )
69
78
)
70
79
71
- compilation . mainTemplate . hooks . renderManifest . tap (
72
- pluginName ,
73
- ( result , { chunk } ) => {
74
- const renderedModules = Array . from ( chunk . modulesIterable ) . filter (
75
- ( module ) => module . type === MODULE_TYPE
76
- )
80
+ const renderManifestFn = ( result , { chunk } ) => {
81
+ const renderedModules = Array . from (
82
+ getModulesIterable ( compilation , chunk )
83
+ ) . filter ( ( module ) => module . type === MODULE_TYPE )
77
84
78
- if ( renderedModules . length > 0 ) {
79
- result . push ( {
80
- render : ( ) =>
81
- this . renderContentAsset (
82
- compilation ,
83
- chunk ,
84
- renderedModules ,
85
- compilation . runtimeTemplate . requestShortener
86
- ) ,
87
- filenameTemplate : ( { chunk : chunkData } ) =>
88
- this . options . moduleFilename ( chunkData ) ,
89
- pathOptions : {
85
+ if ( renderedModules . length > 0 ) {
86
+ result . push ( {
87
+ render : ( ) =>
88
+ this . renderContentAsset (
89
+ compilation ,
90
90
chunk ,
91
- contentHashType : MODULE_TYPE ,
92
- } ,
93
- identifier : `${ pluginName } .${ chunk . id } ` ,
94
- hash : chunk . contentHash [ MODULE_TYPE ] ,
95
- } )
96
- }
91
+ renderedModules ,
92
+ compilation . runtimeTemplate . requestShortener
93
+ ) ,
94
+ filenameTemplate : ( { chunk : chunkData } ) =>
95
+ this . options . moduleFilename ( chunkData ) ,
96
+ pathOptions : {
97
+ chunk,
98
+ contentHashType : MODULE_TYPE ,
99
+ } ,
100
+ identifier : `${ pluginName } .${ chunk . id } ` ,
101
+ hash : chunk . contentHash [ MODULE_TYPE ] ,
102
+ } )
97
103
}
98
- )
99
-
100
- compilation . chunkTemplate . hooks . renderManifest . tap (
101
- pluginName ,
102
- ( result , { chunk } ) => {
103
- const renderedModules = Array . from ( chunk . modulesIterable ) . filter (
104
- ( module ) => module . type === MODULE_TYPE
105
- )
104
+ }
106
105
107
- if ( renderedModules . length > 0 ) {
108
- result . push ( {
109
- render : ( ) =>
110
- this . renderContentAsset (
111
- compilation ,
112
- chunk ,
113
- renderedModules ,
114
- compilation . runtimeTemplate . requestShortener
115
- ) ,
116
- filenameTemplate : this . options . chunkFilename ,
117
- pathOptions : {
118
- chunk,
119
- contentHashType : MODULE_TYPE ,
120
- } ,
121
- identifier : `${ pluginName } .${ chunk . id } ` ,
122
- hash : chunk . contentHash [ MODULE_TYPE ] ,
123
- } )
124
- }
125
- }
126
- )
106
+ if ( isWebpack5 ) {
107
+ compilation . hooks . renderManifest . tap ( pluginName , renderManifestFn )
108
+ } else {
109
+ // In webpack 5 the 2 separate hooks are now one hook: `compilation.hooks.renderManifest`
110
+ // So we no longer have to double-apply the same function
111
+ compilation . mainTemplate . hooks . renderManifest . tap (
112
+ pluginName ,
113
+ renderManifestFn
114
+ )
115
+ compilation . chunkTemplate . hooks . renderManifest . tap (
116
+ pluginName ,
117
+ renderManifestFn
118
+ )
119
+ }
127
120
128
- compilation . mainTemplate . hooks . hashForChunk . tap (
129
- pluginName ,
130
- ( hash , chunk ) => {
131
- const { chunkFilename } = this . options
121
+ const handleHashForChunk = ( hash , chunk ) => {
122
+ const { chunkFilename } = this . options
132
123
133
- if ( REGEXP_CHUNKHASH . test ( chunkFilename ) ) {
134
- hash . update ( JSON . stringify ( chunk . getChunkMaps ( true ) . hash ) )
135
- }
124
+ if ( REGEXP_CHUNKHASH . test ( chunkFilename ) ) {
125
+ hash . update ( JSON . stringify ( chunk . getChunkMaps ( true ) . hash ) )
126
+ }
136
127
137
- if ( REGEXP_CONTENTHASH . test ( chunkFilename ) ) {
138
- hash . update (
139
- JSON . stringify (
140
- chunk . getChunkMaps ( true ) . contentHash [ MODULE_TYPE ] || { }
141
- )
128
+ if ( REGEXP_CONTENTHASH . test ( chunkFilename ) ) {
129
+ hash . update (
130
+ JSON . stringify (
131
+ chunk . getChunkMaps ( true ) . contentHash [ MODULE_TYPE ] || { }
142
132
)
143
- }
133
+ )
134
+ }
144
135
145
- if ( REGEXP_NAME . test ( chunkFilename ) ) {
146
- hash . update ( JSON . stringify ( chunk . getChunkMaps ( true ) . name ) )
147
- }
136
+ if ( REGEXP_NAME . test ( chunkFilename ) ) {
137
+ hash . update ( JSON . stringify ( chunk . getChunkMaps ( true ) . name ) )
148
138
}
149
- )
139
+ }
140
+ if ( isWebpack5 ) {
141
+ const JSModulesHooks = webpack . javascript . JavascriptModulesPlugin . getCompilationHooks (
142
+ compilation
143
+ )
144
+ JSModulesHooks . chunkHash . tap ( pluginName , ( chunk , hash ) => {
145
+ if ( ! chunk . hasRuntime ( ) ) return
146
+ return handleHashForChunk ( hash , chunk )
147
+ } )
148
+ } else {
149
+ compilation . mainTemplate . hooks . hashForChunk . tap (
150
+ pluginName ,
151
+ handleHashForChunk
152
+ )
153
+ }
150
154
151
155
compilation . hooks . contentHash . tap ( pluginName , ( chunk ) => {
152
156
const { outputOptions } = compilation
153
157
const { hashFunction, hashDigest, hashDigestLength } = outputOptions
154
158
const hash = createHash ( hashFunction )
155
159
156
- for ( const m of chunk . modulesIterable ) {
157
- if ( m . type === MODULE_TYPE ) {
158
- m . updateHash ( hash )
160
+ const modules = getModulesIterable ( compilation , chunk )
161
+
162
+ if ( modules ) {
163
+ if ( isWebpack5 ) {
164
+ const xor = new ( require ( 'webpack/lib/util/StringXor' ) ) ( )
165
+ for ( const m of modules ) {
166
+ if ( m . type === MODULE_TYPE ) {
167
+ xor . add ( compilation . chunkGraph . getModuleHash ( m , chunk . runtime ) )
168
+ }
169
+ }
170
+ xor . updateHash ( hash )
171
+ } else {
172
+ for ( const m of modules ) {
173
+ if ( m . type === MODULE_TYPE ) {
174
+ m . updateHash ( hash )
175
+ }
176
+ }
159
177
}
160
178
}
161
179
@@ -169,7 +187,7 @@ class MiniCssExtractPlugin {
169
187
const { mainTemplate } = compilation
170
188
171
189
mainTemplate . hooks . localVars . tap ( pluginName , ( source , chunk ) => {
172
- const chunkMap = this . getCssChunkObject ( chunk )
190
+ const chunkMap = this . getCssChunkObject ( compilation , chunk )
173
191
174
192
if ( Object . keys ( chunkMap ) . length > 0 ) {
175
193
return Template . asString ( [
@@ -190,7 +208,7 @@ class MiniCssExtractPlugin {
190
208
mainTemplate . hooks . requireEnsure . tap (
191
209
pluginName ,
192
210
( source , chunk , hash ) => {
193
- const chunkMap = this . getCssChunkObject ( chunk )
211
+ const chunkMap = this . getCssChunkObject ( compilation , chunk )
194
212
195
213
if ( Object . keys ( chunkMap ) . length > 0 ) {
196
214
const chunkMaps = chunk . getChunkMaps ( )
@@ -322,11 +340,11 @@ class MiniCssExtractPlugin {
322
340
} )
323
341
}
324
342
325
- getCssChunkObject ( mainChunk ) {
343
+ getCssChunkObject ( compilation , mainChunk ) {
326
344
const obj = { }
327
345
328
346
for ( const chunk of mainChunk . getAllAsyncChunks ( ) ) {
329
- for ( const module of chunk . modulesIterable ) {
347
+ for ( const module of getModulesIterable ( compilation , chunk ) ) {
330
348
if ( module . type === MODULE_TYPE ) {
331
349
obj [ chunk . id ] = 1
332
350
break
@@ -342,7 +360,9 @@ class MiniCssExtractPlugin {
342
360
343
361
const [ chunkGroup ] = chunk . groupsIterable
344
362
345
- if ( typeof chunkGroup . getModuleIndex2 === 'function' ) {
363
+ const getModulePostOrderIndex =
364
+ chunkGroup . getModulePostOrderIndex || chunkGroup . getModuleIndex2
365
+ if ( typeof getModulePostOrderIndex === 'function' ) {
346
366
// Store dependencies for modules
347
367
const moduleDependencies = new Map ( modules . map ( ( m ) => [ m , new Set ( ) ] ) )
348
368
const moduleDependenciesReasons = new Map (
@@ -357,7 +377,9 @@ class MiniCssExtractPlugin {
357
377
. map ( ( m ) => {
358
378
return {
359
379
module : m ,
360
- index : cg . getModuleIndex2 ( m ) ,
380
+ index : isWebpack5
381
+ ? cg . getModulePostOrderIndex ( m )
382
+ : cg . getModuleIndex2 ( m ) ,
361
383
}
362
384
} )
363
385
// eslint-disable-next-line no-undefined
0 commit comments