2
2
3
3
const path = require ( 'path' )
4
4
const split = require ( 'css-split' )
5
- const { RawSource } = require ( 'webpack-sources ' )
5
+ const { sources : { RawSource } , Compilation } = require ( 'webpack' )
6
6
const { interpolateName } = require ( 'loader-utils' )
7
7
8
8
/**
@@ -68,27 +68,32 @@ const normalizeImports = (input, preserve) => {
68
68
class FastCSSSplitWebpackPlugin {
69
69
/**
70
70
* Create new instance of FastCSSSplitWebpackPlugin.
71
- * @param {Number } size Maximum number of rules for a single file.
72
- * @param {Boolean|String } imports Truish to generate an additional import
71
+ * @param [options]
72
+ * @param {Number } [options.size] Maximum number of rules for a single file.
73
+ * @param {Boolean|String } [options.imports] Truish to generate an additional import
73
74
* asset. When a boolean use the default name for the asset.
74
- * @param {String } filename Control the generated split file name.
75
- * @param {Boolean } defer Defer splitting until the `emit` phase. Normally
76
- * only needed if something else in your pipeline is mangling things at
77
- * the emit phase too.
78
- * @param {Boolean } preserve True to keep the original unsplit file.
75
+ * @param {String } [options.filename] Control the generated split file name.
76
+ * @param {Number } [options.stage] only valid while [options.defer] is false
77
+ * see <https://webpack.js.org/api/compilation-hooks/#additional-assets>
78
+ * @param {Boolean } [options.defer] Defer splitting until the `afterProcessAssets`
79
+ * phase. Normally only needed if something else in your pipeline is mangling
80
+ * things at the same phase too.
81
+ * @param {Boolean } [options.preserve] True to keep the original unsplit file.
79
82
*/
80
83
constructor ( {
81
84
size = 4000 ,
82
85
imports = false ,
83
86
filename = '[name]-[part].[ext]' ,
84
87
preserve,
88
+ stage = Compilation . PROCESS_ASSETS_STAGE_DEV_TOOLING ,
85
89
defer = false
86
- } ) {
90
+ } = { } ) {
87
91
this . options = {
88
92
size,
89
93
imports : normalizeImports ( imports , preserve ) ,
90
94
filename : nameInterpolator ( filename ) ,
91
95
preserve,
96
+ stage,
92
97
defer
93
98
}
94
99
}
@@ -97,7 +102,6 @@ class FastCSSSplitWebpackPlugin {
97
102
* Generate the split chunks for a given CSS file.
98
103
* @param {String } key Name of the file.
99
104
* @param {Object } asset Valid webpack Source object.
100
- * @returns {Promise } Promise generating array of new files.
101
105
*/
102
106
file ( key , asset ) {
103
107
const input = {
@@ -124,12 +128,12 @@ class FastCSSSplitWebpackPlugin {
124
128
}
125
129
}
126
130
127
- chunksMapping ( compilation , chunks , done ) {
131
+ chunksMapping ( compilation ) {
128
132
const assets = compilation . assets
129
133
const publicPath = strip ( compilation . options . output . publicPath || './' )
130
134
131
- chunks . map ( ( chunk ) => {
132
- const input = chunk . files . filter ( isCSS )
135
+ for ( const chunk of compilation . chunks ) {
136
+ const input = [ ... chunk . files ] . filter ( isCSS )
133
137
const entries = input . map ( ( name ) => this . file ( name , assets [ name ] ) )
134
138
135
139
entries . forEach ( ( entry ) => {
@@ -145,7 +149,7 @@ class FastCSSSplitWebpackPlugin {
145
149
// - ...
146
150
entry . chunks . forEach ( ( file ) => {
147
151
assets [ file . fullname ] = file
148
- chunk . files . push ( file . fullname )
152
+ chunk . files . add ( file . fullname )
149
153
} )
150
154
151
155
// generate imports file content
@@ -162,7 +166,7 @@ class FastCSSSplitWebpackPlugin {
162
166
163
167
// if chunks.length == 1, the original chunk will be always preserved
164
168
if ( entry . chunks . length > 1 && ! this . options . preserve ) {
165
- chunk . files . splice ( chunk . files . indexOf ( entry . file ) , 1 )
169
+ chunk . files . delete ( entry . file )
166
170
delete assets [ entry . file ]
167
171
}
168
172
@@ -176,12 +180,10 @@ class FastCSSSplitWebpackPlugin {
176
180
imports = `${ entry . dirname } /${ imports } `
177
181
}
178
182
assets [ imports ] = importsFile
179
- chunk . files . push ( imports )
183
+ chunk . files . add ( imports )
180
184
}
181
185
} )
182
- } )
183
-
184
- done ( )
186
+ }
185
187
}
186
188
187
189
/**
@@ -195,44 +197,25 @@ class FastCSSSplitWebpackPlugin {
195
197
* @returns {void }
196
198
*/
197
199
apply ( compiler ) {
198
- // for webpack 4
199
- if ( compiler . hooks ) {
200
- const plugin = {
201
- name : 'FastCssSplitPlugin'
202
- }
203
-
204
- if ( this . options . defer ) {
205
- // Run on `emit ` when user specifies the compiler phase
200
+ const name = 'FastCssSplitPlugin'
201
+ const { defer , stage } = this . options
202
+
203
+ // Only run on `thisCompilation` to avoid injecting the plugin into
204
+ // sub-compilers as happens when using the `mini-css-extract-plugin`.
205
+ compiler . hooks . thisCompilation . tap ( name , compilation => {
206
+ if ( defer ) {
207
+ // Run on `afterProcessAssets ` when user specifies the compiler phase
206
208
// Due to the incorrect css split + optimization behavior
207
209
// Expected: css split should happen after optimization
208
- compiler . hooks . emit . tapAsync ( plugin , ( compilation , done ) => {
209
- this . chunksMapping ( compilation , compilation . chunks , done )
210
+ compilation . hooks . afterProcessAssets . tap ( name , ( ) => {
211
+ this . chunksMapping ( compilation )
210
212
} )
211
213
} else {
212
- // use compilation instead of this-compilation, just like other plugins do
213
- compiler . hooks . compilation . tap ( plugin , compilation => {
214
- compilation . hooks . optimizeChunkAssets . tapAsync ( plugin , ( chunks , done ) => {
215
- this . chunksMapping ( compilation , chunks , done )
216
- } )
214
+ compilation . hooks . processAssets . tap ( { name, stage } , ( ) => {
215
+ this . chunksMapping ( compilation )
217
216
} )
218
217
}
219
- } else {
220
- if ( this . options . defer ) {
221
- // Run on `emit` when user specifies the compiler phase
222
- // Due to the incorrect css split + optimization behavior
223
- // Expected: css split should happen after optimization
224
- compiler . plugin ( 'emit' , ( compilation , done ) => {
225
- return this . chunksMapping ( compilation , compilation . chunks , done )
226
- } )
227
- } else {
228
- // use compilation instead of this-compilation, just like other plugins do
229
- compiler . plugin ( 'compilation' , ( compilation ) => {
230
- compilation . plugin ( 'optimize-chunk-assets' , ( chunks , done ) => {
231
- return this . chunksMapping ( compilation , chunks , done )
232
- } )
233
- } )
234
- }
235
- }
218
+ } )
236
219
}
237
220
}
238
221
0 commit comments