@@ -28,6 +28,10 @@ class JsonpMainTemplatePlugin {
28
28
}
29
29
return false ;
30
30
} ;
31
+ const needPrefetchingCode = chunk => {
32
+ const allPrefetchChunks = chunk . getChildIdsByOrdersMap ( true ) . prefetch ;
33
+ return allPrefetchChunks && Object . keys ( allPrefetchChunks ) . length ;
34
+ } ;
31
35
// TODO refactor this
32
36
if ( ! mainTemplate . hooks . jsonpScript ) {
33
37
mainTemplate . hooks . jsonpScript = new SyncWaterfallHook ( [
@@ -232,9 +236,21 @@ class JsonpMainTemplatePlugin {
232
236
mainTemplate . hooks . linkPrefetch . tap (
233
237
"JsonpMainTemplatePlugin" ,
234
238
( _ , chunk , hash ) => {
239
+ const crossOriginLoading =
240
+ mainTemplate . outputOptions . crossOriginLoading ;
241
+
235
242
return Template . asString ( [
236
243
"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
+ "}" ,
237
252
'link.rel = "prefetch";' ,
253
+ 'link.as = "script";' ,
238
254
"link.href = jsonpScriptSrc(chunkId);"
239
255
] ) ;
240
256
}
@@ -288,7 +304,7 @@ class JsonpMainTemplatePlugin {
288
304
"" ,
289
305
"// chunk preloadng for javascript" ,
290
306
"" ,
291
- `var chunkPreloadMap = ${ JSON . stringify ( chunkMap , null , "\t" ) } ` ,
307
+ `var chunkPreloadMap = ${ JSON . stringify ( chunkMap , null , "\t" ) } ; ` ,
292
308
"" ,
293
309
"var chunkPreloadData = chunkPreloadMap[chunkId];" ,
294
310
"if(chunkPreloadData) {" ,
@@ -310,45 +326,6 @@ class JsonpMainTemplatePlugin {
310
326
] ) ;
311
327
}
312
328
) ;
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
- ) ;
352
329
mainTemplate . hooks . requireExtensions . tap (
353
330
"JsonpMainTemplatePlugin" ,
354
331
( source , chunk ) => {
@@ -369,6 +346,7 @@ class JsonpMainTemplatePlugin {
369
346
( source , chunk , hash ) => {
370
347
if ( needChunkLoadingCode ( chunk ) ) {
371
348
const withDefer = needEntryDeferringCode ( chunk ) ;
349
+ const withPrefetch = needPrefetchingCode ( chunk ) ;
372
350
return Template . asString ( [
373
351
source ,
374
352
"" ,
@@ -378,6 +356,7 @@ class JsonpMainTemplatePlugin {
378
356
"var chunkIds = data[0];" ,
379
357
"var moreModules = data[1];" ,
380
358
withDefer ? "var executeModules = data[2];" : "" ,
359
+ withPrefetch ? "var prefetchChunks = data[3] || [];" : "" ,
381
360
'// add "moreModules" to the modules object,' ,
382
361
'// then flag all "chunkIds" as loaded and fire callback' ,
383
362
"var moduleId, chunkId, i = 0, resolves = [];" ,
@@ -405,6 +384,23 @@ class JsonpMainTemplatePlugin {
405
384
] ) ,
406
385
"}" ,
407
386
"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
+ : "" ,
408
404
"while(resolves.length) {" ,
409
405
Template . indent ( "resolves.shift()();" ) ,
410
406
"}" ,
@@ -479,6 +475,25 @@ class JsonpMainTemplatePlugin {
479
475
return source ;
480
476
}
481
477
) ;
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
+ ) ;
482
497
mainTemplate . hooks . startup . tap (
483
498
"JsonpMainTemplatePlugin" ,
484
499
( source , chunk , hash ) => {
0 commit comments