Skip to content

Commit

Permalink
Merge pull request #7444 from MLoughry/prefetch-from-entry
Browse files Browse the repository at this point in the history
Prefetch and preload  from entry chunk.
  • Loading branch information
sokra committed Jun 4, 2018
2 parents fe3ca80 + c65d164 commit bc6b5b0
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 139 deletions.
13 changes: 11 additions & 2 deletions lib/Chunk.js
Expand Up @@ -607,10 +607,10 @@ class Chunk {
return result;
}

getChildIdsByOrdersMap() {
getChildIdsByOrdersMap(includeDirectChildren) {
const chunkMaps = Object.create(null);

for (const chunk of this.getAllAsyncChunks()) {
const addChildIdsByOrdersToMap = chunk => {
const data = chunk.getChildIdsByOrders();
for (const key of Object.keys(data)) {
let chunkMap = chunkMaps[key];
Expand All @@ -619,7 +619,16 @@ class Chunk {
}
chunkMap[chunk.id] = data[key];
}
};

if (includeDirectChildren) {
addChildIdsByOrdersToMap(this);
}

for (const chunk of this.getAllAsyncChunks()) {
addChildIdsByOrdersToMap(chunk);
}

return chunkMaps;
}

Expand Down
7 changes: 7 additions & 0 deletions lib/web/JsonpChunkTemplatePlugin.js
Expand Up @@ -14,6 +14,7 @@ class JsonpChunkTemplatePlugin {
const jsonpFunction = chunkTemplate.outputOptions.jsonpFunction;
const globalObject = chunkTemplate.outputOptions.globalObject;
const source = new ConcatSource();
const prefetchChunks = chunk.getChildIdsByOrders().prefetch;
source.add(
`(${globalObject}[${JSON.stringify(
jsonpFunction
Expand All @@ -31,6 +32,12 @@ class JsonpChunkTemplatePlugin {
);
if (entries.length > 0) {
source.add(`,${JSON.stringify(entries)}`);
} else if (prefetchChunks && prefetchChunks.length) {
source.add(`,0`);
}

if (prefetchChunks && prefetchChunks.length) {
source.add(`,${JSON.stringify(prefetchChunks)}`);
}
source.add("])");
return source;
Expand Down
95 changes: 55 additions & 40 deletions lib/web/JsonpMainTemplatePlugin.js
Expand Up @@ -28,6 +28,10 @@ class JsonpMainTemplatePlugin {
}
return false;
};
const needPrefetchingCode = chunk => {
const allPrefetchChunks = chunk.getChildIdsByOrdersMap(true).prefetch;
return allPrefetchChunks && Object.keys(allPrefetchChunks).length;
};
// TODO refactor this
if (!mainTemplate.hooks.jsonpScript) {
mainTemplate.hooks.jsonpScript = new SyncWaterfallHook([
Expand Down Expand Up @@ -232,9 +236,21 @@ class JsonpMainTemplatePlugin {
mainTemplate.hooks.linkPrefetch.tap(
"JsonpMainTemplatePlugin",
(_, chunk, hash) => {
const crossOriginLoading =
mainTemplate.outputOptions.crossOriginLoading;

return Template.asString([
"var link = document.createElement('link');",
crossOriginLoading
? `link.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
: "",
`if (${mainTemplate.requireFn}.nc) {`,
Template.indent(
`link.setAttribute("nonce", ${mainTemplate.requireFn}.nc);`
),
"}",
'link.rel = "prefetch";',
'link.as = "script";',
"link.href = jsonpScriptSrc(chunkId);"
]);
}
Expand Down Expand Up @@ -288,7 +304,7 @@ class JsonpMainTemplatePlugin {
"",
"// chunk preloadng for javascript",
"",
`var chunkPreloadMap = ${JSON.stringify(chunkMap, null, "\t")}`,
`var chunkPreloadMap = ${JSON.stringify(chunkMap, null, "\t")};`,
"",
"var chunkPreloadData = chunkPreloadMap[chunkId];",
"if(chunkPreloadData) {",
Expand All @@ -310,45 +326,6 @@ class JsonpMainTemplatePlugin {
]);
}
);
mainTemplate.hooks.requireEnsure.tap(
{
name: "JsonpMainTemplatePlugin prefetch",
stage: 20
},
(source, chunk, hash) => {
const chunkMap = chunk.getChildIdsByOrdersMap().prefetch;
if (!chunkMap || Object.keys(chunkMap).length === 0) return source;
return Template.asString([
source,
"",
"// chunk prefetching for javascript",
"",
`var chunkPrefetchMap = ${JSON.stringify(chunkMap, null, "\t")}`,
"",
"var chunkPrefetchData = chunkPrefetchMap[chunkId];",
"if(chunkPrefetchData) {",
Template.indent([
"Promise.all(promises).then(function() {",
Template.indent([
"var head = document.getElementsByTagName('head')[0];",
"chunkPrefetchData.forEach(function(chunkId) {",
Template.indent([
"if(installedChunks[chunkId] === undefined) {",
Template.indent([
"installedChunks[chunkId] = null;",
mainTemplate.hooks.linkPrefetch.call("", chunk, hash),
"head.appendChild(link);"
]),
"}"
]),
"});"
]),
"})"
]),
"}"
]);
}
);
mainTemplate.hooks.requireExtensions.tap(
"JsonpMainTemplatePlugin",
(source, chunk) => {
Expand All @@ -369,6 +346,7 @@ class JsonpMainTemplatePlugin {
(source, chunk, hash) => {
if (needChunkLoadingCode(chunk)) {
const withDefer = needEntryDeferringCode(chunk);
const withPrefetch = needPrefetchingCode(chunk);
return Template.asString([
source,
"",
Expand All @@ -378,6 +356,7 @@ class JsonpMainTemplatePlugin {
"var chunkIds = data[0];",
"var moreModules = data[1];",
withDefer ? "var executeModules = data[2];" : "",
withPrefetch ? "var prefetchChunks = data[3] || [];" : "",
'// add "moreModules" to the modules object,',
'// then flag all "chunkIds" as loaded and fire callback',
"var moduleId, chunkId, i = 0, resolves = [];",
Expand Down Expand Up @@ -405,6 +384,23 @@ class JsonpMainTemplatePlugin {
]),
"}",
"if(parentJsonpFunction) parentJsonpFunction(data);",
withPrefetch
? Template.asString([
"// chunk prefetching for javascript",
"var head = document.getElementsByTagName('head')[0];",
"prefetchChunks.forEach(function(chunkId) {",
Template.indent([
"if(installedChunks[chunkId] === undefined) {",
Template.indent([
"installedChunks[chunkId] = null;",
mainTemplate.hooks.linkPrefetch.call("", chunk, hash),
"head.appendChild(link);"
]),
"}"
]),
"});"
])
: "",
"while(resolves.length) {",
Template.indent("resolves.shift()();"),
"}",
Expand Down Expand Up @@ -479,6 +475,25 @@ class JsonpMainTemplatePlugin {
return source;
}
);
mainTemplate.hooks.beforeStartup.tap(
"JsonpMainTemplatePlugin",
(source, chunk, hash) => {
const prefetchChunks = chunk.getChildIdsByOrders().prefetch;
if (
needChunkLoadingCode(chunk) &&
prefetchChunks &&
prefetchChunks.length
) {
return Template.asString([
source,
`webpackJsonpCallback([[], {}, 0, ${JSON.stringify(
prefetchChunks
)}]);`
]);
}
return source;
}
);
mainTemplate.hooks.startup.tap(
"JsonpMainTemplatePlugin",
(source, chunk, hash) => {
Expand Down
4 changes: 3 additions & 1 deletion test/ConfigTestCases.test.js
Expand Up @@ -7,6 +7,7 @@ const vm = require("vm");
const mkdirp = require("mkdirp");
const rimraf = require("rimraf");
const checkArrayExpectation = require("./checkArrayExpectation");
const FakeDocument = require("./helpers/FakeDocument");

const Stats = require("../lib/Stats");
const webpack = require("../lib/webpack");
Expand Down Expand Up @@ -176,7 +177,8 @@ describe("ConfigTestCases", () => {
console: console,
expect: expect,
setTimeout: setTimeout,
clearTimeout: clearTimeout
clearTimeout: clearTimeout,
document: new FakeDocument()
};

function _require(currentDirectory, module) {
Expand Down

0 comments on commit bc6b5b0

Please sign in to comment.