@@ -15,6 +15,7 @@ const {
15
15
compareModulesByIdentifier,
16
16
getUndoPath,
17
17
BASE_URI ,
18
+ compileBooleanMatcher,
18
19
} = require ( "./utils" ) ;
19
20
20
21
/** @typedef {import("schema-utils/declarations/validate").Schema } Schema */
@@ -106,6 +107,8 @@ const CODE_GENERATION_RESULT = {
106
107
/**
107
108
* @typedef {Object } MiniCssExtractPluginCompilationHooks
108
109
* @property {import("tapable").SyncWaterfallHook<[string, VarNames], string> } beforeTagInsert
110
+ * @property {SyncWaterfallHook<[string, Chunk]> } linkPreload
111
+ * @property {SyncWaterfallHook<[string, Chunk]> } linkPrefetch
109
112
*/
110
113
111
114
/**
@@ -527,7 +530,8 @@ class MiniCssExtractPlugin {
527
530
528
531
/**
529
532
* Returns all hooks for the given compilation
530
- * @param {Compilation } compilation
533
+ * @param {Compilation } compilation the compilation
534
+ * @returns {MiniCssExtractPluginCompilationHooks } hooks
531
535
*/
532
536
static getCompilationHooks ( compilation ) {
533
537
let hooks = compilationHooksMap . get ( compilation ) ;
@@ -538,6 +542,8 @@ class MiniCssExtractPlugin {
538
542
[ "source" , "varNames" ] ,
539
543
"string"
540
544
) ,
545
+ linkPreload : new SyncWaterfallHook ( [ "source" , "chunk" ] ) ,
546
+ linkPrefetch : new SyncWaterfallHook ( [ "source" , "chunk" ] ) ,
541
547
} ;
542
548
compilationHooksMap . set ( compilation , hooks ) ;
543
549
}
@@ -842,6 +848,20 @@ class MiniCssExtractPlugin {
842
848
return obj ;
843
849
} ;
844
850
851
+ /**
852
+ * @param {Chunk } chunk chunk
853
+ * @param {ChunkGraph } chunkGraph chunk graph
854
+ * @returns {boolean } true, when the chunk has css
855
+ */
856
+ function chunkHasCss ( chunk , chunkGraph ) {
857
+ // this function replace:
858
+ // const chunkHasCss = require("webpack/lib/css/CssModulesPlugin").chunkHasCss;
859
+ return ! ! chunkGraph . getChunkModulesIterableBySourceType (
860
+ chunk ,
861
+ "css/mini-extract"
862
+ ) ;
863
+ }
864
+
845
865
class CssLoadingRuntimeModule extends RuntimeModule {
846
866
/**
847
867
* @param {Set<string> } runtimeRequirements
@@ -855,7 +875,7 @@ class MiniCssExtractPlugin {
855
875
}
856
876
857
877
generate ( ) {
858
- const { chunk, runtimeRequirements } = this ;
878
+ const { chunkGraph , chunk, runtimeRequirements } = this ;
859
879
const {
860
880
runtimeTemplate,
861
881
outputOptions : { crossOriginLoading } ,
@@ -864,7 +884,6 @@ class MiniCssExtractPlugin {
864
884
/** @type {Chunk } */ ( chunk ) ,
865
885
/** @type {Compilation } */ ( this . compilation )
866
886
) ;
867
-
868
887
const withLoading =
869
888
runtimeRequirements . has ( RuntimeGlobals . ensureChunkHandlers ) &&
870
889
Object . keys ( chunkMap ) . length > 0 ;
@@ -875,6 +894,20 @@ class MiniCssExtractPlugin {
875
894
if ( ! withLoading && ! withHmr ) {
876
895
return "" ;
877
896
}
897
+
898
+ const conditionMap = /** @type {ChunkGraph } */ (
899
+ chunkGraph
900
+ ) . getChunkConditionMap ( /** @type {Chunk } */ ( chunk ) , chunkHasCss ) ;
901
+ const hasCssMatcher = compileBooleanMatcher ( conditionMap ) ;
902
+ const withPrefetch = runtimeRequirements . has (
903
+ RuntimeGlobals . prefetchChunkHandlers
904
+ ) ;
905
+ const withPreload = runtimeRequirements . has (
906
+ RuntimeGlobals . preloadChunkHandlers
907
+ ) ;
908
+ const { linkPreload, linkPrefetch } =
909
+ MiniCssExtractPlugin . getCompilationHooks ( compilation ) ;
910
+
878
911
return Template . asString ( [
879
912
'if (typeof document === "undefined") return;' ,
880
913
`var createStylesheet = ${ runtimeTemplate . basicFunction (
@@ -1089,6 +1122,87 @@ class MiniCssExtractPlugin {
1089
1122
) } `,
1090
1123
] )
1091
1124
: "// no hmr" ,
1125
+ "" ,
1126
+ withPrefetch && hasCssMatcher !== false
1127
+ ? `${
1128
+ RuntimeGlobals . prefetchChunkHandlers
1129
+ } .miniCss = ${ runtimeTemplate . basicFunction ( "chunkId" , [
1130
+ `if((!${
1131
+ RuntimeGlobals . hasOwnProperty
1132
+ } (installedCssChunks, chunkId) || installedCssChunks[chunkId] === undefined) && ${
1133
+ hasCssMatcher === true ? "true" : hasCssMatcher ( "chunkId" )
1134
+ } ) {`,
1135
+ Template . indent ( [
1136
+ "installedCssChunks[chunkId] = null;" ,
1137
+ linkPrefetch . call (
1138
+ Template . asString ( [
1139
+ "var link = document.createElement('link');" ,
1140
+ crossOriginLoading
1141
+ ? `link.crossOrigin = ${ JSON . stringify (
1142
+ crossOriginLoading
1143
+ ) } ;`
1144
+ : "" ,
1145
+ `if (${ RuntimeGlobals . scriptNonce } ) {` ,
1146
+ Template . indent (
1147
+ `link.setAttribute("nonce", ${ RuntimeGlobals . scriptNonce } );`
1148
+ ) ,
1149
+ "}" ,
1150
+ 'link.rel = "prefetch";' ,
1151
+ 'link.as = "style";' ,
1152
+ `link.href = ${ RuntimeGlobals . publicPath } + ${ RuntimeGlobals . require } .miniCssF(chunkId);` ,
1153
+ ] ) ,
1154
+ /** @type {Chunk } */ ( chunk )
1155
+ ) ,
1156
+ "document.head.appendChild(link);" ,
1157
+ ] ) ,
1158
+ "}" ,
1159
+ ] ) } ;`
1160
+ : "// no prefetching" ,
1161
+ "" ,
1162
+ withPreload && hasCssMatcher !== false
1163
+ ? `${
1164
+ RuntimeGlobals . preloadChunkHandlers
1165
+ } .miniCss = ${ runtimeTemplate . basicFunction ( "chunkId" , [
1166
+ `if((!${
1167
+ RuntimeGlobals . hasOwnProperty
1168
+ } (installedCssChunks, chunkId) || installedCssChunks[chunkId] === undefined) && ${
1169
+ hasCssMatcher === true ? "true" : hasCssMatcher ( "chunkId" )
1170
+ } ) {`,
1171
+ Template . indent ( [
1172
+ "installedCssChunks[chunkId] = null;" ,
1173
+ linkPreload . call (
1174
+ Template . asString ( [
1175
+ "var link = document.createElement('link');" ,
1176
+ "link.charset = 'utf-8';" ,
1177
+ `if (${ RuntimeGlobals . scriptNonce } ) {` ,
1178
+ Template . indent (
1179
+ `link.setAttribute("nonce", ${ RuntimeGlobals . scriptNonce } );`
1180
+ ) ,
1181
+ "}" ,
1182
+ 'link.rel = "preload";' ,
1183
+ 'link.as = "style";' ,
1184
+ `link.href = ${ RuntimeGlobals . publicPath } + ${ RuntimeGlobals . require } .miniCssF(chunkId);` ,
1185
+ crossOriginLoading
1186
+ ? crossOriginLoading === "use-credentials"
1187
+ ? 'link.crossOrigin = "use-credentials";'
1188
+ : Template . asString ( [
1189
+ "if (link.href.indexOf(window.location.origin + '/') !== 0) {" ,
1190
+ Template . indent (
1191
+ `link.crossOrigin = ${ JSON . stringify (
1192
+ crossOriginLoading
1193
+ ) } ;`
1194
+ ) ,
1195
+ "}" ,
1196
+ ] )
1197
+ : "" ,
1198
+ ] ) ,
1199
+ /** @type {Chunk } */ ( chunk )
1200
+ ) ,
1201
+ "document.head.appendChild(link);" ,
1202
+ ] ) ,
1203
+ "}" ,
1204
+ ] ) } ;`
1205
+ : "// no preloaded" ,
1092
1206
] ) ;
1093
1207
}
1094
1208
}
@@ -1150,6 +1264,12 @@ class MiniCssExtractPlugin {
1150
1264
compilation . hooks . runtimeRequirementInTree
1151
1265
. for ( RuntimeGlobals . hmrDownloadUpdateHandlers )
1152
1266
. tap ( pluginName , handler ) ;
1267
+ compilation . hooks . runtimeRequirementInTree
1268
+ . for ( RuntimeGlobals . prefetchChunkHandlers )
1269
+ . tap ( pluginName , handler ) ;
1270
+ compilation . hooks . runtimeRequirementInTree
1271
+ . for ( RuntimeGlobals . preloadChunkHandlers )
1272
+ . tap ( pluginName , handler ) ;
1153
1273
} ) ;
1154
1274
}
1155
1275
0 commit comments