Skip to content

Commit 0d21ce1

Browse files
committed
Address most of Sokra's comments
- [x] Don't emit prefetch code if not needed - [x] Only affect StatsTestCase dealing with prefetching - [x] Fix existing prefetch test case - [ ] Trigger prefetch after startup code runs - [ ] Add new test(s)
1 parent 88d09b0 commit 0d21ce1

File tree

5 files changed

+64
-49
lines changed

5 files changed

+64
-49
lines changed

lib/Chunk.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,10 +607,10 @@ class Chunk {
607607
return result;
608608
}
609609

610-
getChildIdsByOrdersMap() {
610+
getChildIdsByOrdersMap(includeDirectChildren) {
611611
const chunkMaps = Object.create(null);
612612

613-
for (const chunk of this.getAllAsyncChunks()) {
613+
function addChildIdsByOrdersToMap(chunk) {
614614
const data = chunk.getChildIdsByOrders();
615615
for (const key of Object.keys(data)) {
616616
let chunkMap = chunkMaps[key];
@@ -620,6 +620,15 @@ class Chunk {
620620
chunkMap[chunk.id] = data[key];
621621
}
622622
}
623+
624+
if (includeDirectChildren) {
625+
addChildIdsByOrdersToMap(this);
626+
}
627+
628+
for (const chunk of this.getAllAsyncChunks()) {
629+
addChildIdsByOrdersToMap(chunk);
630+
}
631+
623632
return chunkMaps;
624633
}
625634

lib/web/JsonpChunkTemplatePlugin.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class JsonpChunkTemplatePlugin {
1414
const jsonpFunction = chunkTemplate.outputOptions.jsonpFunction;
1515
const globalObject = chunkTemplate.outputOptions.globalObject;
1616
const source = new ConcatSource();
17+
const prefetchChunks = chunk.getChildIdsByOrders().prefetch;
1718
source.add(
1819
`(${globalObject}[${JSON.stringify(
1920
jsonpFunction
@@ -31,16 +32,12 @@ class JsonpChunkTemplatePlugin {
3132
);
3233
if (entries.length > 0) {
3334
source.add(`,${JSON.stringify(entries)}`);
34-
} else {
35-
source.add(`,null`);
35+
} else if (prefetchChunks && prefetchChunks.length) {
36+
source.add(`,0`);
3637
}
37-
if (
38-
chunk.getChildIdsByOrders().prefetch &&
39-
chunk.getChildIdsByOrders().prefetch.length
40-
) {
41-
source.add(
42-
`,${JSON.stringify(chunk.getChildIdsByOrders().prefetch)}`
43-
);
38+
39+
if (prefetchChunks && prefetchChunks.length) {
40+
source.add(`,${JSON.stringify(prefetchChunks)}`);
4441
}
4542
source.add("])");
4643
return source;

lib/web/JsonpMainTemplatePlugin.js

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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([
@@ -330,6 +334,7 @@ class JsonpMainTemplatePlugin {
330334
(source, chunk, hash) => {
331335
if (needChunkLoadingCode(chunk)) {
332336
const withDefer = needEntryDeferringCode(chunk);
337+
const withPrefetch = needPrefetchingCode(chunk);
333338
return Template.asString([
334339
source,
335340
"",
@@ -339,7 +344,7 @@ class JsonpMainTemplatePlugin {
339344
"var chunkIds = data[0];",
340345
"var moreModules = data[1];",
341346
withDefer ? "var executeModules = data[2];" : "",
342-
"var prefetchChunks = data[3] || []",
347+
...(withPrefetch ? ["var prefetchChunks = data[3] || []"] : []),
343348
'// add "moreModules" to the modules object,',
344349
'// then flag all "chunkIds" as loaded and fire callback',
345350
"var moduleId, chunkId, i = 0, resolves = [];",
@@ -380,20 +385,23 @@ class JsonpMainTemplatePlugin {
380385
"return checkDeferredModules();"
381386
])
382387
: "",
383-
"",
384-
"// chunk prefetching for javascript",
385-
"var head = document.getElementsByTagName('head')[0];",
386-
"prefetchChunks.forEach(function(chunkId) {",
387-
Template.indent([
388-
"if(installedChunks[chunkId] === undefined) {",
389-
Template.indent([
390-
"installedChunks[chunkId] = null;",
391-
mainTemplate.hooks.linkPrefetch.call("", chunk, hash),
392-
"head.appendChild(link);"
393-
]),
394-
"}"
395-
]),
396-
"});"
388+
...(withPrefetch
389+
? [
390+
"// chunk prefetching for javascript",
391+
"var head = document.getElementsByTagName('head')[0];",
392+
"prefetchChunks.forEach(function(chunkId) {",
393+
Template.indent([
394+
"if(installedChunks[chunkId] === undefined) {",
395+
Template.indent([
396+
"installedChunks[chunkId] = null;",
397+
mainTemplate.hooks.linkPrefetch.call("", chunk, hash),
398+
"head.appendChild(link);"
399+
]),
400+
"}"
401+
]),
402+
"});"
403+
]
404+
: [])
397405
]),
398406
"};",
399407
withDefer
@@ -458,14 +466,17 @@ class JsonpMainTemplatePlugin {
458466
mainTemplate.hooks.beforeStartup.tap(
459467
"JsonpMainTemplatePlugin",
460468
(source, chunk, hash) => {
461-
if (needChunkLoadingCode(chunk)) {
469+
const prefetchChunks = chunk.getChildIdsByOrders().prefetch;
470+
if (
471+
needChunkLoadingCode(chunk) &&
472+
prefetchChunks &&
473+
prefetchChunks.length
474+
) {
462475
return Template.asString([
463476
source,
464477
`webpackJsonpCallback([${JSON.stringify(
465478
chunk.ids
466-
)}, {}, null, ${JSON.stringify(
467-
chunk.getChildIdsByOrders().prefetch
468-
)}])`
479+
)}, {}, null, ${JSON.stringify(prefetchChunks)}])`
469480
]);
470481
}
471482
return source;

test/__snapshots__/StatsTestCases.test.js.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,11 +1668,11 @@ For more info visit https://webpack.js.org/guides/code-splitting/</CLR>"
16681668

16691669
exports[`StatsTestCases should print correct stats for prefetch 1`] = `
16701670
" Asset Size Chunks Chunk Names
1671-
prefetched.js 467 bytes 0 [emitted] prefetched
1671+
prefetched.js 475 bytes 0 [emitted] prefetched
16721672
normal.js 130 bytes 1 [emitted] normal
16731673
prefetched2.js 127 bytes 2 [emitted] prefetched2
16741674
prefetched3.js 130 bytes 3 [emitted] prefetched3
1675-
main.js 9.73 KiB 4 [emitted] main
1675+
main.js 9.5 KiB 4 [emitted] main
16761676
inner.js 136 bytes 5 [emitted] inner
16771677
inner2.js 201 bytes 6 [emitted] inner2
16781678
Entrypoint main = main.js (prefetch: prefetched2.js prefetched.js prefetched3.js)

test/configCases/web/prefetch-preload/index.js

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,26 @@ it("should prefetch and preload child chunks on chunk load", (done) => {
2222
__webpack_public_path__ = "/public/path/";
2323

2424
const promise = import(/* webpackChunkName: "chunk1" */ "./chunk1");
25-
expect(document.head._children).toHaveLength(2);
26-
const script = document.head._children[0];
25+
expect(document.head._children).toHaveLength(4);
26+
27+
let link = document.head._children[0];
28+
expect(link._type).toBe("link");
29+
expect(link.rel).toBe("prefetch");
30+
expect(link.href).toBe("/public/path/chunk1-c.js");
31+
32+
link = document.head._children[1];
33+
expect(link._type).toBe("link");
34+
expect(link.rel).toBe("prefetch");
35+
expect(link.href).toBe("/public/path/chunk1-a.js");
36+
37+
const script = document.head._children[2];
2738
expect(script._type).toBe("script");
2839
expect(script.src).toBe("/public/path/chunk1.js")
2940
expect(script.getAttribute("nonce")).toBe("nonce")
3041
expect(script.crossOrigin).toBe("anonymous");
3142
expect(script.onload).toBeTypeOf("function");
3243

33-
let link = document.head._children[1];
44+
link = document.head._children[3];
3445
expect(link._type).toBe("link");
3546
expect(link.rel).toBe("preload");
3647
expect(link.as).toBe("script");
@@ -42,18 +53,5 @@ it("should prefetch and preload child chunks on chunk load", (done) => {
4253
__non_webpack_require__("./chunk1.js");
4354
script.onload();
4455

45-
return promise.then((ex) => {
46-
expect(document.head._children).toHaveLength(4);
47-
48-
let link = document.head._children[2];
49-
expect(link._type).toBe("link");
50-
expect(link.rel).toBe("prefetch");
51-
expect(link.href).toBe("/public/path/chunk1-c.js");
52-
53-
link = document.head._children[3];
54-
expect(link._type).toBe("link");
55-
expect(link.rel).toBe("prefetch");
56-
expect(link.href).toBe("/public/path/chunk1-a.js");
57-
done();
58-
}, done);
56+
return promise.then(() => done(), done);
5957
})

0 commit comments

Comments
 (0)