@@ -15,6 +15,7 @@ const {
1515 compareModulesByIdentifier,
1616 getUndoPath,
1717 BASE_URI ,
18+ compileBooleanMatcher,
1819} = require ( "./utils" ) ;
1920
2021/** @typedef {import("schema-utils/declarations/validate").Schema } Schema */
@@ -106,6 +107,8 @@ const CODE_GENERATION_RESULT = {
106107/**
107108 * @typedef {Object } MiniCssExtractPluginCompilationHooks
108109 * @property {import("tapable").SyncWaterfallHook<[string, VarNames], string> } beforeTagInsert
110+ * @property {SyncWaterfallHook<[string, Chunk]> } linkPreload
111+ * @property {SyncWaterfallHook<[string, Chunk]> } linkPrefetch
109112 */
110113
111114/**
@@ -527,7 +530,8 @@ class MiniCssExtractPlugin {
527530
528531 /**
529532 * Returns all hooks for the given compilation
530- * @param {Compilation } compilation
533+ * @param {Compilation } compilation the compilation
534+ * @returns {MiniCssExtractPluginCompilationHooks } hooks
531535 */
532536 static getCompilationHooks ( compilation ) {
533537 let hooks = compilationHooksMap . get ( compilation ) ;
@@ -538,6 +542,8 @@ class MiniCssExtractPlugin {
538542 [ "source" , "varNames" ] ,
539543 "string"
540544 ) ,
545+ linkPreload : new SyncWaterfallHook ( [ "source" , "chunk" ] ) ,
546+ linkPrefetch : new SyncWaterfallHook ( [ "source" , "chunk" ] ) ,
541547 } ;
542548 compilationHooksMap . set ( compilation , hooks ) ;
543549 }
@@ -842,6 +848,20 @@ class MiniCssExtractPlugin {
842848 return obj ;
843849 } ;
844850
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+
845865 class CssLoadingRuntimeModule extends RuntimeModule {
846866 /**
847867 * @param {Set<string> } runtimeRequirements
@@ -855,7 +875,7 @@ class MiniCssExtractPlugin {
855875 }
856876
857877 generate ( ) {
858- const { chunk, runtimeRequirements } = this ;
878+ const { chunkGraph , chunk, runtimeRequirements } = this ;
859879 const {
860880 runtimeTemplate,
861881 outputOptions : { crossOriginLoading } ,
@@ -864,7 +884,6 @@ class MiniCssExtractPlugin {
864884 /** @type {Chunk } */ ( chunk ) ,
865885 /** @type {Compilation } */ ( this . compilation )
866886 ) ;
867-
868887 const withLoading =
869888 runtimeRequirements . has ( RuntimeGlobals . ensureChunkHandlers ) &&
870889 Object . keys ( chunkMap ) . length > 0 ;
@@ -875,6 +894,20 @@ class MiniCssExtractPlugin {
875894 if ( ! withLoading && ! withHmr ) {
876895 return "" ;
877896 }
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+
878911 return Template . asString ( [
879912 'if (typeof document === "undefined") return;' ,
880913 `var createStylesheet = ${ runtimeTemplate . basicFunction (
@@ -1089,6 +1122,87 @@ class MiniCssExtractPlugin {
10891122 ) } `,
10901123 ] )
10911124 : "// 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" ,
10921206 ] ) ;
10931207 }
10941208 }
@@ -1150,6 +1264,12 @@ class MiniCssExtractPlugin {
11501264 compilation . hooks . runtimeRequirementInTree
11511265 . for ( RuntimeGlobals . hmrDownloadUpdateHandlers )
11521266 . 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 ) ;
11531273 } ) ;
11541274 }
11551275
0 commit comments