2
2
3
3
import webpack from 'webpack' ;
4
4
import sources from 'webpack-sources' ;
5
- import NullFactory from 'webpack/lib/NullFactory' ;
6
-
7
- import ReplaceDependency from './lib/ReplaceDependency' ;
8
5
9
6
const { ConcatSource, SourceMapSource, OriginalSource } = sources ;
10
7
const {
@@ -22,6 +19,16 @@ const REGEXP_NAME = /\[name\]/i;
22
19
const REGEXP_PLACEHOLDERS = / \[ ( n a m e | i d | c h u n k h a s h ) \] / g;
23
20
const DEFAULT_FILENAME = '[name].css' ;
24
21
22
+ function isInitialOrHasNoParents ( chunk ) {
23
+ let parentCount = 0 ;
24
+
25
+ for ( const chunkGroup of chunk . groupsIterable ) {
26
+ parentCount += chunkGroup . getNumberOfParents ( ) ;
27
+ }
28
+
29
+ return chunk . isOnlyInitial ( ) || parentCount === 0 ;
30
+ }
31
+
25
32
class CssDependency extends webpack . Dependency {
26
33
constructor (
27
34
{ identifier, content, media, sourceMap } ,
@@ -157,12 +164,6 @@ class MiniCssExtractPlugin {
157
164
moduleToBeRebuild,
158
165
} ;
159
166
160
- compilation . dependencyFactories . set ( ReplaceDependency , new NullFactory ( ) ) ;
161
- compilation . dependencyTemplates . set (
162
- ReplaceDependency ,
163
- new ReplaceDependency . Template ( )
164
- ) ;
165
-
166
167
compilation . hooks . normalModuleLoader . tap ( pluginName , ( lc , m ) => {
167
168
const loaderContext = lc ;
168
169
const module = m ;
@@ -185,6 +186,10 @@ class MiniCssExtractPlugin {
185
186
identifierCountMap . set ( line . identifier , count + 1 ) ;
186
187
}
187
188
} ;
189
+
190
+ loaderContext [ `${ MODULE_TYPE } /disableExtract` ] = ( ) => {
191
+ return ! ! module [ `${ MODULE_TYPE } /disableExtract` ] ;
192
+ } ;
188
193
} ) ;
189
194
190
195
compilation . dependencyFactories . set (
@@ -202,8 +207,7 @@ class MiniCssExtractPlugin {
202
207
( result , { chunk } ) => {
203
208
const renderedModules = Array . from ( chunk . modulesIterable ) . filter (
204
209
( module ) =>
205
- module . type === MODULE_TYPE &&
206
- ! this . shouldDisableExtract ( { module, isAsync : false } )
210
+ module . type === MODULE_TYPE && ! moduleToBeRebuild . has ( module )
207
211
) ;
208
212
209
213
if ( renderedModules . length > 0 ) {
@@ -452,46 +456,53 @@ class MiniCssExtractPlugin {
452
456
}
453
457
) ;
454
458
455
- const len = `// extracted by ${ pluginName } ` . length ;
456
- mainTemplate . hooks . beforeStartup . tap ( pluginName , ( source ) => {
457
- for ( const currentModuleToBeRebuild of moduleToBeRebuild ) {
458
- const issuerDeps = currentModuleToBeRebuild . issuer . dependencies ;
459
- let firstIndex = - 1 ;
460
- const content = [ ] ;
461
-
462
- for ( let i = issuerDeps . length - 1 ; i >= 0 ; i -- ) {
463
- const { module } = issuerDeps [ i ] ;
464
- if ( moduleToBeRebuild . has ( module ) ) {
465
- firstIndex = i ;
466
- content . unshift ( module . content . replace ( / (?: [ \r \n ] + ) / g, '\\n' ) ) ;
467
- issuerDeps . splice ( i , 1 ) ;
459
+ compilation . hooks . optimizeTree . tapAsync (
460
+ pluginName ,
461
+ ( chunks , modules , callback ) => {
462
+ const promises = [ ] ;
463
+
464
+ for ( const chunk of chunks ) {
465
+ const isAsync = ! isInitialOrHasNoParents ( chunk ) ;
466
+ // eslint-disable-next-line no-underscore-dangle
467
+ for ( const module of chunk . _modules ) {
468
+ if ( module . type === MODULE_TYPE ) {
469
+ if ( this . shouldDisableExtract ( { module, isAsync } ) ) {
470
+ moduleToBeRebuild . add ( module ) ;
471
+ }
472
+ }
468
473
}
469
474
}
470
475
471
- if ( firstIndex > - 1 ) {
472
- issuerDeps . splice (
473
- firstIndex ,
474
- 0 ,
475
- new ReplaceDependency ( `module.exports = "${ content . join ( '' ) } ";` , [
476
- 0 ,
477
- len ,
478
- ] )
479
- ) ;
476
+ for ( const currentModuleToBeRebuild of moduleToBeRebuild ) {
477
+ const { issuer } = currentModuleToBeRebuild ;
478
+ if ( ! issuer [ `${ MODULE_TYPE } /disableExtract` ] ) {
479
+ issuer [ `${ MODULE_TYPE } /disableExtract` ] = true ;
480
+ promises . push (
481
+ new Promise ( ( resolve ) => {
482
+ compilation . rebuildModule ( issuer , ( err ) => {
483
+ if ( err ) {
484
+ compilation . errors . push ( err ) ;
485
+ }
486
+ resolve ( ) ;
487
+ } ) ;
488
+ } )
489
+ ) ;
490
+ }
480
491
}
481
- }
482
492
483
- return source ;
484
- } ) ;
493
+ Promise . all ( promises ) . then ( ( ) => callback ( ) ) ;
494
+ }
495
+ ) ;
485
496
} ) ;
486
497
}
487
498
488
- shouldDisableExtract ( { module } ) {
499
+ shouldDisableExtract ( { module, isAsync } ) {
489
500
const { disableExtract } = this . options ;
490
501
let shouldDisable = false ;
491
502
if ( disableExtract === true ) {
492
503
shouldDisable = true ;
493
504
} else if ( typeof disableExtract === 'function' ) {
494
- shouldDisable = disableExtract ( { module } ) ;
505
+ shouldDisable = disableExtract ( { module, isAsync } ) ;
495
506
}
496
507
497
508
return shouldDisable ;
@@ -503,23 +514,14 @@ class MiniCssExtractPlugin {
503
514
for ( const chunk of mainChunk . getAllAsyncChunks ( ) ) {
504
515
for ( const module of chunk . modulesIterable ) {
505
516
if ( module . type === MODULE_TYPE ) {
506
- if ( this . shouldDisableExtract ( { module, isAsync : true } ) ) {
507
- compilation [ MODULE_TYPE ] . moduleToBeRebuild . add ( module ) ;
508
- } else {
517
+ if ( ! compilation [ MODULE_TYPE ] . moduleToBeRebuild . has ( module ) ) {
509
518
obj [ chunk . id ] = 1 ;
519
+ break ;
510
520
}
511
521
}
512
522
}
513
523
}
514
524
515
- for ( const module of mainChunk . modulesIterable ) {
516
- if ( module . type === MODULE_TYPE ) {
517
- if ( this . shouldDisableExtract ( { module, isAsync : false } ) ) {
518
- compilation [ MODULE_TYPE ] . moduleToBeRebuild . add ( module ) ;
519
- }
520
- }
521
- }
522
-
523
525
return obj ;
524
526
}
525
527
0 commit comments