put runtime modules into separate place in chunks

don't include them in modules array/object
better stats output for runtime moduels
This commit is contained in:
Tobias Koppers 2018-11-29 14:13:02 +01:00
parent 7eff4c300f
commit 8066eaf299
15 changed files with 364 additions and 325 deletions

View File

@ -1416,6 +1416,9 @@ class Compilation {
RuntimeGlobals.require
]);
// runtime modules don't need ids
this.chunkGraph.setModuleId(module, "");
// Call hook
this.hooks.runtimeModule.call(module, chunk);
}

View File

@ -67,7 +67,6 @@ class JavascriptModulesPlugin {
if (module.type === "javascript/auto") return true;
if (module.type === "javascript/dynamic") return true;
if (module.type === "javascript/esm") return true;
if (module.type === "runtime") return true;
});
normalModuleFactory.hooks.createParser
.for("javascript/auto")

View File

@ -72,6 +72,12 @@ module.exports = class MainTemplate {
"moduleTemplate",
"renderContext"
]),
/** @type {SyncWaterfallHook<Source, ModuleTemplate, MainRenderContext>} */
runtimeModules: new SyncWaterfallHook([
"source",
"moduleTemplate",
"renderContext"
]),
/** @type {SyncWaterfallHook<string, RenderBootstrapContext>} */
bootstrap: new SyncWaterfallHook(["source", "renderContext"]),
/** @type {SyncWaterfallHook<string, Chunk, string>} */
@ -80,8 +86,6 @@ module.exports = class MainTemplate {
require: new SyncWaterfallHook(["source", "renderContext"]),
/** @type {SyncWaterfallHook<string, RenderBootstrapContext>} */
requireExtensions: new SyncWaterfallHook(["source", "renderContext"]),
/** @type {SyncWaterfallHook<string, RenderBootstrapContext>} */
runtime: new SyncWaterfallHook(["source", "renderContext"]),
/** @type {SyncWaterfallHook<string, Chunk, string>} */
beforeStartup: new SyncWaterfallHook(["source", "chunk", "hash"]),
/** @type {SyncWaterfallHook<string, RenderBootstrapContext>} */
@ -150,7 +154,10 @@ module.exports = class MainTemplate {
"MainTemplate",
(bootstrapSource, moduleTemplate, renderContext) => {
const source = new ConcatSource();
source.add("/******/ (function(modules) { // webpackBootstrap\n");
source.add(
"/******/ (function(modules, runtime) { // webpackBootstrap\n"
);
source.add('/******/"use strict";\n');
source.add(new PrefixSource("/******/", bootstrapSource));
source.add("/******/ })\n");
source.add(
@ -164,6 +171,15 @@ module.exports = class MainTemplate {
renderContext
)
);
const runtimeModules = renderContext.chunkGraph.getChunkRuntimeModulesInOrder(
renderContext.chunk
);
if (runtimeModules.length > 0) {
source.add(",");
source.add(
Template.renderChunkRuntimeModules(runtimeModules, renderContext)
);
}
source.add(")");
return source;
}
@ -294,7 +310,13 @@ module.exports = class MainTemplate {
Template.asString(this.hooks.requireExtensions.call("", renderContext))
);
buf.push("");
buf.push(Template.asString(this.hooks.runtime.call("", renderContext)));
if (
renderContext.chunkGraph.getNumberOfRuntimeModules(renderContext.chunk) >
0
) {
buf.push("// initialize runtime");
buf.push("runtime(__webpack_require__);");
}
buf.push(Template.asString(this.hooks.beforeStartup.call("", chunk, hash)));
buf.push(Template.asString(this.hooks.startup.call("", renderContext)));
return buf;

View File

@ -6,7 +6,6 @@
"use strict";
const RuntimeGlobals = require("./RuntimeGlobals");
const Template = require("./Template");
const CompatGetDefaultExportRuntimeModule = require("./runtime/CompatGetDefaultExportRuntimeModule");
const CreateFakeNamespaceObjectRuntimeModule = require("./runtime/CreateFakeNamespaceObjectRuntimeModule");
const DefinePropertyGetterRuntimeModule = require("./runtime/DefinePropertyGetterRuntimeModule");
@ -178,26 +177,6 @@ class RuntimePlugin {
);
return true;
});
compilation.mainTemplate.hooks.runtime.tap(
"RuntimePlugin",
(source, { chunk, chunkGraph }) => {
const buf = [];
const runtimeModules = chunkGraph.getChunkRuntimeModulesInOrder(
chunk
);
if (runtimeModules.length > 0) {
buf.push("// Bootstrap all runtime modules");
for (const module of runtimeModules) {
buf.push(
`// ${module.name}\nmodules[${JSON.stringify(
chunkGraph.getModuleId(module)
)}](0,0,__webpack_require__);`
);
}
}
return Template.asString(buf);
}
);
});
}
}

View File

@ -602,6 +602,7 @@ class Stats {
cacheable: module.buildInfo.cacheable,
built: compilation.builtModules.has(module),
optional: module.isOptional(moduleGraph),
runtime: module.type === "runtime",
chunks: Array.from(
chunkGraph.getOrderedModuleChunksIterable(module, compareChunksById),
chunk => chunk.id
@ -1162,6 +1163,9 @@ class Stats {
if (module.orphan) {
colors.yellow(" [orphan]");
}
if (module.runtime) {
colors.yellow(" [runtime]");
}
if (module.optional) {
colors.yellow(" [optional]");
}
@ -1336,7 +1340,10 @@ class Stats {
for (const module of obj.modules) {
colors.normal(prefix);
const name = module.name || module.identifier;
if (typeof module.id === "string" || typeof module.id === "number") {
if (
(typeof module.id === "string" && module.id !== "") ||
typeof module.id === "number"
) {
if (typeof module.id === "number") {
if (module.id < 1000 && maxModuleId >= 1000) colors.normal(" ");
if (module.id < 100 && maxModuleId >= 100) colors.normal(" ");
@ -1535,6 +1542,8 @@ class Stats {
optimizationBailout: true,
errorDetails: true,
publicPath: true,
orphanModules: true,
runtime: true,
exclude: false,
maxModules: Infinity
};
@ -1551,6 +1560,8 @@ class Stats {
optimizationBailout: true,
errorDetails: true,
publicPath: true,
runtimeModules: true,
runtime: true,
exclude: false,
maxModules: Infinity
};

View File

@ -5,7 +5,7 @@
"use strict";
const { ConcatSource } = require("webpack-sources");
const { ConcatSource, PrefixSource } = require("webpack-sources");
const HotUpdateChunk = require("./HotUpdateChunk");
const { compareIds } = require("./util/comparators");
@ -19,6 +19,7 @@ const { compareIds } = require("./util/comparators");
/** @typedef {import("./ModuleGraph")} ModuleGraph */
/** @typedef {import("./ModuleTemplate")} ModuleTemplate */
/** @typedef {import("./ModuleTemplate").RenderContext} RenderContext */
/** @typedef {import("./RuntimeModule")} RuntimeModule */
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
const START_LOWERCASE_ALPHABET_CODE = "a".charCodeAt(0);
@ -311,6 +312,33 @@ class Template {
}
return source;
}
/**
* @param {RuntimeModule[]} runtimeModules array of runtime modules in order
* @param {RenderContext} renderContext render context
* @returns {Source} rendered chunk runtime modules in a Source object
*/
static renderChunkRuntimeModules(runtimeModules, renderContext) {
const source = new ConcatSource();
for (const module of runtimeModules) {
const moduleSource = module.source({
chunkGraph: renderContext.chunkGraph,
dependencyTemplates: renderContext.dependencyTemplates,
moduleGraph: renderContext.moduleGraph,
runtimeTemplate: renderContext.runtimeTemplate,
type: "runtime"
});
source.add(Template.toNormalComment(module.identifier()) + "\n");
source.add("!function() {\n");
source.add(new PrefixSource("\t", moduleSource));
source.add("\n}();\n\n");
}
return new ConcatSource(
'function(__webpack_require__) {\n"use strict";\n\n',
new PrefixSource("\t", source),
"}\n"
);
}
}
module.exports = Template;

View File

@ -274,7 +274,7 @@ module.exports = function() {
// run new runtime modules
for (var i = 0; i < $updateRuntimeModules$.length; i++) {
appliedUpdate[$updateRuntimeModules$[i]](0, 0, __webpack_require__);
$updateRuntimeModules$[i](__webpack_require__);
}
// call accept handlers

View File

@ -6,15 +6,10 @@
"use strict";
const { ConcatSource } = require("webpack-sources");
const Template = require("../Template");
/** @typedef {import("../ChunkTemplate")} ChunkTemplate */
const getRuntimeModuleIds = (chunkGraph, chunk) => {
return chunkGraph
.getChunkRuntimeModulesInOrder(chunk)
.map(m => chunkGraph.getModuleId(m));
};
class NodeChunkTemplatePlugin {
constructor(compilation) {
this.compilation = compilation;
@ -26,27 +21,25 @@ class NodeChunkTemplatePlugin {
apply(chunkTemplate) {
chunkTemplate.hooks.render.tap(
"NodeChunkTemplatePlugin",
(modules, moduleTemplate, { chunk, chunkGraph }) => {
(modules, moduleTemplate, renderContext) => {
const { chunk, chunkGraph } = renderContext;
const source = new ConcatSource();
source.add(`exports.id = ${JSON.stringify(chunk.id)};\n`);
source.add(`exports.ids = ${JSON.stringify(chunk.ids)};\n`);
source.add(`exports.modules = `);
source.add(modules);
source.add(";\n");
const runtimeModules = getRuntimeModuleIds(chunkGraph, chunk);
const runtimeModules = chunkGraph.getChunkRuntimeModulesInOrder(chunk);
if (runtimeModules.length > 0) {
source.add(`exports.runtime = ${JSON.stringify(runtimeModules)};\n`);
source.add("exports.runtime = ");
source.add(
Template.renderChunkRuntimeModules(runtimeModules, renderContext)
);
source.add(";\n");
}
return source;
}
);
chunkTemplate.hooks.hashForChunk.tap(
"NodeChunkTemplatePlugin",
(hash, chunk) => {
const chunkGraph = this.compilation.chunkGraph;
hash.update(JSON.stringify(getRuntimeModuleIds(chunkGraph, chunk)));
}
);
chunkTemplate.hooks.hash.tap("NodeChunkTemplatePlugin", hash => {
hash.update("node");
hash.update("5");

View File

@ -78,7 +78,7 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
"}"
]),
"}",
`if(runtime) for(var i = 0; i < runtime.length; i++) moreModules[runtime[i]](0,0,__webpack_require__);`,
`if(runtime) runtime(__webpack_require__);`,
"var callbacks = [];",
"for(var i = 0; i < chunkIds.length; i++) {",
Template.indent([
@ -141,7 +141,7 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
"}"
]),
"}",
"if(runtime) for(var i = 0; i < runtime.length; i++) currentUpdateRuntime.push(runtime[i]);",
"if(runtime) currentUpdateRuntime.push(runtime);",
"resolve();"
]),
"});"

View File

@ -63,7 +63,7 @@ class RequireChunkLoadingRuntimeModule extends RuntimeModule {
"}"
]),
"}",
`if(runtime) for(var i = 0; i < runtime.length; i++) moreModules[runtime[i]](0,0,__webpack_require__);`,
`if(runtime) runtime(__webpack_require__);`,
"for(var i = 0; i < chunkIds.length; i++)",
Template.indent("installedChunks[chunkIds[i]] = 1;"),
"",
@ -101,7 +101,7 @@ class RequireChunkLoadingRuntimeModule extends RuntimeModule {
"}"
]),
"}",
"if(runtime) for(var i = 0; i < runtime.length; i++) currentUpdateRuntime.push(runtime[i]);"
"if(runtime) currentUpdateRuntime.push(runtime);"
]),
"}",
"",

View File

@ -226,7 +226,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
"}"
]),
"}",
"if(runtime) for(var i = 0; i < runtime.length; i++) currentUpdateRuntime.push(runtime[i]);",
"if(runtime) currentUpdateRuntime.push(runtime);",
"if(waitingUpdateResolves[chunkId]) {",
Template.indent([
"waitingUpdateResolves[chunkId]();",
@ -369,7 +369,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
"}"
]),
"}",
"if(runtime) for(var i = 0; i < runtime.length; i++) moreModules[runtime[i]](0,0,__webpack_require__);",
"if(runtime) runtime(__webpack_require__);",
"if(parentJsonpFunction) parentJsonpFunction(data);",
withPrefetch
? Template.asString([

View File

@ -7,6 +7,7 @@
const { ConcatSource } = require("webpack-sources");
const HotUpdateChunk = require("../HotUpdateChunk");
const Template = require("../Template");
const getEntryInfo = require("./JsonpHelpers").getEntryInfo;
/** @typedef {import("../Chunk")} Chunk */
@ -28,22 +29,22 @@ class JsonpChunkTemplatePlugin {
apply(chunkTemplate) {
chunkTemplate.hooks.render.tap(
"JsonpChunkTemplatePlugin",
(modules, moduleTemplate, { chunk, chunkGraph }) => {
(modules, moduleTemplate, renderContext) => {
const { chunk, chunkGraph } = renderContext;
const hotUpdateChunk = chunk instanceof HotUpdateChunk ? chunk : null;
const globalObject = chunkTemplate.outputOptions.globalObject;
const source = new ConcatSource();
const runtimeModules = chunkGraph.getChunkRuntimeModulesInOrder(chunk);
const runtimePart =
runtimeModules.length > 0 &&
`,${JSON.stringify(
runtimeModules.map(m => chunkGraph.getModuleId(m))
)}`;
Template.renderChunkRuntimeModules(runtimeModules, renderContext);
if (hotUpdateChunk) {
const jsonpFunction = chunkTemplate.outputOptions.hotUpdateFunction;
source.add(`${globalObject}[${JSON.stringify(jsonpFunction)}](`);
source.add(`${JSON.stringify(chunk.id)},`);
source.add(modules);
if (runtimePart) {
source.add(",");
source.add(runtimePart);
}
source.add(")");
@ -70,7 +71,8 @@ class JsonpChunkTemplatePlugin {
source.add(entriesPart || ",0");
}
if (runtimePart || prefetchPart) {
source.add(runtimePart || ",0");
source.add(",");
source.add(runtimePart || "0");
}
if (prefetchPart) {
source.add(prefetchPart);
@ -95,10 +97,6 @@ class JsonpChunkTemplatePlugin {
hash.update(
JSON.stringify(chunk.getChildIdsByOrders(chunkGraph).prefetch) || ""
);
const runtimeModules = chunkGraph.getChunkRuntimeModulesInOrder(chunk);
hash.update(
JSON.stringify(runtimeModules.map(m => chunkGraph.getModuleId(m)))
);
}
);
}

View File

@ -64,7 +64,7 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule {
"}"
]),
"}",
"if(runtime) for(var i = 0; i < runtime.length; i++) moreModules[runtime[i]](0,0,__webpack_require__);",
"if(runtime) runtime(__webpack_require__);",
"while(chunkIds.length)",
Template.indent("installedChunks[chunkIds.pop()] = 1;")
]),
@ -105,7 +105,7 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule {
"}"
]),
"}",
"if(runtime) for(var i = 0; i < runtime.length; i++) currentUpdateRuntime.push(runtime[i]);",
"if(runtime) currentUpdateRuntime.push(runtime);",
"success = true;"
]),
"};",

View File

@ -7,6 +7,7 @@
const { ConcatSource } = require("webpack-sources");
const HotUpdateChunk = require("../HotUpdateChunk");
const Template = require("../Template");
/** @typedef {import("../ChunkTemplate")} ChunkTemplate */
/** @typedef {import("../Compilation")} Compilation */
@ -26,21 +27,21 @@ class WebWorkerChunkTemplatePlugin {
apply(chunkTemplate) {
chunkTemplate.hooks.render.tap(
"WebWorkerChunkTemplatePlugin",
(modules, moduleTemplate, { chunk, chunkGraph }) => {
(modules, moduleTemplate, renderContext) => {
const { chunk, chunkGraph } = renderContext;
const hotUpdateChunk = chunk instanceof HotUpdateChunk ? chunk : null;
const globalObject = chunkTemplate.outputOptions.globalObject;
const source = new ConcatSource();
const runtimeModules = chunkGraph.getChunkRuntimeModulesInOrder(chunk);
const runtimePart =
runtimeModules.length > 0 &&
`,${JSON.stringify(
runtimeModules.map(m => chunkGraph.getModuleId(m))
)}`;
Template.renderChunkRuntimeModules(runtimeModules, renderContext);
if (hotUpdateChunk) {
const jsonpFunction = chunkTemplate.outputOptions.hotUpdateFunction;
source.add(`${globalObject}[${JSON.stringify(jsonpFunction)}](`);
source.add(modules);
if (runtimePart) {
source.add(",");
source.add(runtimePart);
}
source.add(")");
@ -51,6 +52,7 @@ class WebWorkerChunkTemplatePlugin {
source.add(`${JSON.stringify(chunk.ids)},`);
source.add(modules);
if (runtimePart) {
source.add(",");
source.add(runtimePart);
}
source.add(")");
@ -65,16 +67,6 @@ class WebWorkerChunkTemplatePlugin {
hash.update(`${chunkTemplate.outputOptions.hotUpdateFunction}`);
hash.update(`${chunkTemplate.outputOptions.globalObject}`);
});
chunkTemplate.hooks.hashForChunk.tap(
"WebWorkerChunkTemplatePlugin",
(hash, chunk) => {
const chunkGraph = this.compilation.chunkGraph;
const runtimeModules = chunkGraph.getChunkRuntimeModulesInOrder(chunk);
hash.update(
JSON.stringify(runtimeModules.map(m => chunkGraph.getModuleId(m)))
);
}
);
}
}
module.exports = WebWorkerChunkTemplatePlugin;

File diff suppressed because it is too large Load Diff