@@ -28,6 +28,10 @@ class JsonpMainTemplatePlugin {
2828 }
2929 return false ;
3030 } ;
31+ const needPrefetchingCode = chunk => {
32+ const allPrefetchChunks = chunk . getChildIdsByOrdersMap ( true ) . prefetch ;
33+ return allPrefetchChunks && Object . keys ( allPrefetchChunks ) . length ;
34+ } ;
3135 // TODO refactor this
3236 if ( ! mainTemplate . hooks . jsonpScript ) {
3337 mainTemplate . hooks . jsonpScript = new SyncWaterfallHook ( [
@@ -232,9 +236,21 @@ class JsonpMainTemplatePlugin {
232236 mainTemplate . hooks . linkPrefetch . tap (
233237 "JsonpMainTemplatePlugin" ,
234238 ( _ , chunk , hash ) => {
239+ const crossOriginLoading =
240+ mainTemplate . outputOptions . crossOriginLoading ;
241+
235242 return Template . asString ( [
236243 "var link = document.createElement('link');" ,
244+ crossOriginLoading
245+ ? `link.crossOrigin = ${ JSON . stringify ( crossOriginLoading ) } ;`
246+ : "" ,
247+ `if (${ mainTemplate . requireFn } .nc) {` ,
248+ Template . indent (
249+ `link.setAttribute("nonce", ${ mainTemplate . requireFn } .nc);`
250+ ) ,
251+ "}" ,
237252 'link.rel = "prefetch";' ,
253+ 'link.as = "script";' ,
238254 "link.href = jsonpScriptSrc(chunkId);"
239255 ] ) ;
240256 }
@@ -288,7 +304,7 @@ class JsonpMainTemplatePlugin {
288304 "" ,
289305 "// chunk preloadng for javascript" ,
290306 "" ,
291- `var chunkPreloadMap = ${ JSON . stringify ( chunkMap , null , "\t" ) } ` ,
307+ `var chunkPreloadMap = ${ JSON . stringify ( chunkMap , null , "\t" ) } ; ` ,
292308 "" ,
293309 "var chunkPreloadData = chunkPreloadMap[chunkId];" ,
294310 "if(chunkPreloadData) {" ,
@@ -310,45 +326,6 @@ class JsonpMainTemplatePlugin {
310326 ] ) ;
311327 }
312328 ) ;
313- mainTemplate . hooks . requireEnsure . tap (
314- {
315- name : "JsonpMainTemplatePlugin prefetch" ,
316- stage : 20
317- } ,
318- ( source , chunk , hash ) => {
319- const chunkMap = chunk . getChildIdsByOrdersMap ( ) . prefetch ;
320- if ( ! chunkMap || Object . keys ( chunkMap ) . length === 0 ) return source ;
321- return Template . asString ( [
322- source ,
323- "" ,
324- "// chunk prefetching for javascript" ,
325- "" ,
326- `var chunkPrefetchMap = ${ JSON . stringify ( chunkMap , null , "\t" ) } ` ,
327- "" ,
328- "var chunkPrefetchData = chunkPrefetchMap[chunkId];" ,
329- "if(chunkPrefetchData) {" ,
330- Template . indent ( [
331- "Promise.all(promises).then(function() {" ,
332- Template . indent ( [
333- "var head = document.getElementsByTagName('head')[0];" ,
334- "chunkPrefetchData.forEach(function(chunkId) {" ,
335- Template . indent ( [
336- "if(installedChunks[chunkId] === undefined) {" ,
337- Template . indent ( [
338- "installedChunks[chunkId] = null;" ,
339- mainTemplate . hooks . linkPrefetch . call ( "" , chunk , hash ) ,
340- "head.appendChild(link);"
341- ] ) ,
342- "}"
343- ] ) ,
344- "});"
345- ] ) ,
346- "})"
347- ] ) ,
348- "}"
349- ] ) ;
350- }
351- ) ;
352329 mainTemplate . hooks . requireExtensions . tap (
353330 "JsonpMainTemplatePlugin" ,
354331 ( source , chunk ) => {
@@ -369,6 +346,7 @@ class JsonpMainTemplatePlugin {
369346 ( source , chunk , hash ) => {
370347 if ( needChunkLoadingCode ( chunk ) ) {
371348 const withDefer = needEntryDeferringCode ( chunk ) ;
349+ const withPrefetch = needPrefetchingCode ( chunk ) ;
372350 return Template . asString ( [
373351 source ,
374352 "" ,
@@ -378,6 +356,7 @@ class JsonpMainTemplatePlugin {
378356 "var chunkIds = data[0];" ,
379357 "var moreModules = data[1];" ,
380358 withDefer ? "var executeModules = data[2];" : "" ,
359+ withPrefetch ? "var prefetchChunks = data[3] || [];" : "" ,
381360 '// add "moreModules" to the modules object,' ,
382361 '// then flag all "chunkIds" as loaded and fire callback' ,
383362 "var moduleId, chunkId, i = 0, resolves = [];" ,
@@ -405,6 +384,23 @@ class JsonpMainTemplatePlugin {
405384 ] ) ,
406385 "}" ,
407386 "if(parentJsonpFunction) parentJsonpFunction(data);" ,
387+ withPrefetch
388+ ? Template . asString ( [
389+ "// chunk prefetching for javascript" ,
390+ "var head = document.getElementsByTagName('head')[0];" ,
391+ "prefetchChunks.forEach(function(chunkId) {" ,
392+ Template . indent ( [
393+ "if(installedChunks[chunkId] === undefined) {" ,
394+ Template . indent ( [
395+ "installedChunks[chunkId] = null;" ,
396+ mainTemplate . hooks . linkPrefetch . call ( "" , chunk , hash ) ,
397+ "head.appendChild(link);"
398+ ] ) ,
399+ "}"
400+ ] ) ,
401+ "});"
402+ ] )
403+ : "" ,
408404 "while(resolves.length) {" ,
409405 Template . indent ( "resolves.shift()();" ) ,
410406 "}" ,
@@ -479,6 +475,25 @@ class JsonpMainTemplatePlugin {
479475 return source ;
480476 }
481477 ) ;
478+ mainTemplate . hooks . beforeStartup . tap (
479+ "JsonpMainTemplatePlugin" ,
480+ ( source , chunk , hash ) => {
481+ const prefetchChunks = chunk . getChildIdsByOrders ( ) . prefetch ;
482+ if (
483+ needChunkLoadingCode ( chunk ) &&
484+ prefetchChunks &&
485+ prefetchChunks . length
486+ ) {
487+ return Template . asString ( [
488+ source ,
489+ `webpackJsonpCallback([[], {}, 0, ${ JSON . stringify (
490+ prefetchChunks
491+ ) } ]);`
492+ ] ) ;
493+ }
494+ return source ;
495+ }
496+ ) ;
482497 mainTemplate . hooks . startup . tap (
483498 "JsonpMainTemplatePlugin" ,
484499 ( source , chunk , hash ) => {
0 commit comments