optimize webpack runtime size

This commit is contained in:
Sergey Melyukov 2019-12-02 17:59:37 +03:00
parent e82b870007
commit 6b59d113a4
12 changed files with 287 additions and 225 deletions

View File

@ -545,7 +545,7 @@ function webpackContext(req) {
${returnModuleObject}
}
function webpackContextResolve(req) {
if(!Object.prototype.hasOwnProperty.call(map, req)) {
if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
var e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
throw e;
@ -584,7 +584,7 @@ function webpackContext(req) {
${returnModuleObject}
}
function webpackContextResolve(req) {
if(!Object.prototype.hasOwnProperty.call(map, req)) {
if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
var e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
throw e;
@ -632,7 +632,7 @@ function webpackAsyncContextResolve(req) {
// Here Promise.resolve().then() is used instead of new Promise() to prevent
// uncaught exception popping up in devtools
return Promise.resolve().then(${arrow ? "() =>" : "function()"} {
if(!Object.prototype.hasOwnProperty.call(map, req)) {
if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
var e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
throw e;
@ -640,7 +640,9 @@ function webpackAsyncContextResolve(req) {
return map[req];
});
}
webpackAsyncContext.keys = function webpackAsyncContextKeys() {
webpackAsyncContext.keys = ${
arrow ? "_ => {" : "function webpackAsyncContextKeys() {"
}
return Object.keys(map);
};
webpackAsyncContext.resolve = webpackAsyncContextResolve;
@ -676,7 +678,7 @@ function webpackAsyncContextResolve(req) {
// Here Promise.resolve().then() is used instead of new Promise() to prevent
// uncaught exception popping up in devtools
return Promise.resolve().then(${arrow ? "() =>" : "function()"} {
if(!Object.prototype.hasOwnProperty.call(map, req)) {
if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
var e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
throw e;
@ -684,7 +686,9 @@ function webpackAsyncContextResolve(req) {
return map[req];
});
}
webpackAsyncContext.keys = function webpackAsyncContextKeys() {
webpackAsyncContext.keys = ${
arrow ? "_ => {" : "function webpackAsyncContextKeys() {"
}
return Object.keys(map);
};
webpackAsyncContext.resolve = webpackAsyncContextResolve;
@ -726,7 +730,7 @@ function webpackAsyncContext(req) {
}
function webpackAsyncContextResolve(req) {
return ${promise}.then(${arrow ? "() =>" : "function()"} {
if(!Object.prototype.hasOwnProperty.call(map, req)) {
if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
var e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
throw e;
@ -734,7 +738,9 @@ function webpackAsyncContextResolve(req) {
return map[req];
});
}
webpackAsyncContext.keys = function webpackAsyncContextKeys() {
webpackAsyncContext.keys = ${
arrow ? "_ => {" : "function webpackAsyncContextKeys() {"
}
return Object.keys(map);
};
webpackAsyncContext.resolve = webpackAsyncContextResolve;
@ -821,7 +827,7 @@ module.exports = webpackAsyncContext;`;
? `${shortMode ? "" : ""}
function webpackAsyncContext(req) {
return Promise.resolve().then(${arrow ? "() =>" : "function()"} {
if(!Object.prototype.hasOwnProperty.call(map, req)) {
if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
var e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
throw e;
@ -832,7 +838,7 @@ function webpackAsyncContext(req) {
});
}`
: `function webpackAsyncContext(req) {
if(!Object.prototype.hasOwnProperty.call(map, req)) {
if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
return Promise.resolve().then(${arrow ? "() =>" : "function()"} {
var e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
@ -848,7 +854,9 @@ function webpackAsyncContext(req) {
return `var map = ${JSON.stringify(map, null, "\t")};
${webpackAsyncContext}
webpackAsyncContext.keys = function webpackAsyncContextKeys() {
webpackAsyncContext.keys = ${
arrow ? "_ => {" : "function webpackAsyncContextKeys() {"
}
return Object.keys(map);
};
webpackAsyncContext.id = ${JSON.stringify(id)};
@ -962,6 +970,7 @@ module.exports = webpackEmptyAsyncContext;`;
this.blocks.map(b => b.dependencies[0])
));
set.push(RuntimeGlobals.module);
set.push(RuntimeGlobals.hasOwnProperty);
if (allDeps.length > 0) {
const asyncMode = this.options.mode;
set.push(RuntimeGlobals.require);

View File

@ -199,3 +199,9 @@ exports.amdOptions = "__webpack_require__.amdO";
* the System polyfill object
*/
exports.system = "__webpack_require__.System";
/**
* the shorthand for Object.prototype.hasOwnProperty
* using of ot decreases the compiled bundle size
*/
exports.hasOwnProperty = "__webpack_require__.hop";

View File

@ -321,9 +321,15 @@ class Template {
const moduleSource = codeGenResult.sources.get("runtime");
if (moduleSource) {
source.add(Template.toNormalComment(module.identifier()) + "\n");
source.add("!function() {\n");
source.add(new PrefixSource("\t", moduleSource));
source.add("\n}();\n\n");
if (renderContext.runtimeTemplate.supportsArrowFunction()) {
source.add("(() => {\n");
source.add(new PrefixSource("\t", moduleSource));
source.add("\n})();\n\n");
} else {
source.add("!function() {\n");
source.add(new PrefixSource("\t", moduleSource));
source.add("\n}();\n\n");
}
}
}
}

View File

@ -892,8 +892,9 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
runtimeRequirements.add(RuntimeGlobals.exports);
runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
runtimeRequirements.add(RuntimeGlobals.hasOwnProperty);
return `if(Object.prototype.hasOwnProperty.call(${name}, ${JSON.stringify(
return `if(${RuntimeGlobals.hasOwnProperty}(${name}, ${JSON.stringify(
valueKey[0]
)})) ${
RuntimeGlobals.definePropertyGetters

View File

@ -489,7 +489,7 @@ class JavascriptModulesPlugin {
let source = new ConcatSource();
let prefix;
if (iife) {
if (runtimeTemplate.supportsConst()) {
if (runtimeTemplate.supportsArrowFunction()) {
source.add("/******/ (() => { // webpackBootstrap\n");
} else {
source.add("/******/ (function() { // webpackBootstrap\n");
@ -571,10 +571,17 @@ class JavascriptModulesPlugin {
const innerStrict = !allStrict && m.buildInfo.strict;
const iife = innerStrict || inlinedModules.size > 1 || chunkModules;
if (iife) {
source.add("!function() {\n");
if (innerStrict) source.add('"use strict";\n');
source.add(renderedModule);
source.add("\n}();\n");
if (runtimeTemplate.supportsArrowFunction()) {
source.add("(() => {\n");
if (innerStrict) source.add('"use strict";\n');
source.add(renderedModule);
source.add("\n})();\n\n");
} else {
source.add("!function() {\n");
if (innerStrict) source.add('"use strict";\n');
source.add(renderedModule);
source.add("\n}();\n");
}
} else {
source.add(renderedModule);
source.add("\n");
@ -703,6 +710,24 @@ class JavascriptModulesPlugin {
buf.push("");
}
if (runtimeRequirements.has(RuntimeGlobals.hasOwnProperty)) {
buf.push("// the shorthand for Object.prototype.hasOwnProperty");
if (runtimeTemplate.supportsArrowFunction()) {
buf.push(
`${RuntimeGlobals.hasOwnProperty} = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);`
);
} else {
buf.push(`${RuntimeGlobals.hasOwnProperty} = function (obj, prop) {`);
buf.push(
Template.indent(
"return Object.prototype.hasOwnProperty.call(obj, prop);"
)
);
buf.push("};");
}
buf.push("");
}
if (
moduleFactories ||
runtimeRequirements.has(RuntimeGlobals.moduleFactoriesAddOnly)

View File

@ -14,6 +14,7 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
constructor(runtimeRequirements) {
super("readFile chunk loading", 10);
this.runtimeRequirements = runtimeRequirements;
this.runtimeRequirements.add(RuntimeGlobals.hasOwnProperty);
}
/**
@ -77,7 +78,7 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
"var moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime;",
"for(var moduleId in moreModules) {",
Template.indent([
"if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {",
`if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
Template.indent([
`${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`
]),
@ -148,7 +149,7 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
"var runtime = update.runtime;",
"for(var moduleId in updatedModules) {",
Template.indent([
"if(Object.prototype.hasOwnProperty.call(updatedModules, moduleId)) {",
`if(${RuntimeGlobals.hasOwnProperty}(updatedModules, moduleId)) {`,
Template.indent([
`currentUpdate[moduleId] = updatedModules[moduleId];`,
"if(updatedModulesList) updatedModulesList.push(moduleId);"

View File

@ -14,6 +14,7 @@ class RequireChunkLoadingRuntimeModule extends RuntimeModule {
constructor(runtimeRequirements) {
super("require chunk loading", 10);
this.runtimeRequirements = runtimeRequirements;
this.runtimeRequirements.add(RuntimeGlobals.hasOwnProperty);
}
/**
@ -62,7 +63,7 @@ class RequireChunkLoadingRuntimeModule extends RuntimeModule {
"var moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime;",
"for(var moduleId in moreModules) {",
Template.indent([
"if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {",
`if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
Template.indent([
`${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`
]),
@ -107,7 +108,7 @@ class RequireChunkLoadingRuntimeModule extends RuntimeModule {
"var runtime = update.runtime;",
"for(var moduleId in updatedModules) {",
Template.indent([
"if(Object.prototype.hasOwnProperty.call(updatedModules, moduleId)) {",
`if(${RuntimeGlobals.hasOwnProperty}(updatedModules, moduleId)) {`,
Template.indent([
`currentUpdate[moduleId] = updatedModules[moduleId];`,
"if(updatedModulesList) updatedModulesList.push(moduleId);"

View File

@ -18,6 +18,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
this.jsonpScript = jsonpScript;
this.linkPreload = linkPreload;
this.linkPrefetch = linkPrefetch;
this.runtimeRequirements.add(RuntimeGlobals.hasOwnProperty);
}
/**
@ -112,7 +113,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
hasJsMatcher !== false
? Template.indent([
"// JSONP chunk loading for javascript",
`var installedChunkData = Object.prototype.hasOwnProperty.call(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;`,
`var installedChunkData = ${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;`,
'if(installedChunkData !== 0) { // 0 means "already installed".',
Template.indent([
"",
@ -141,7 +142,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
`var loadingEnded = ${runtimeTemplate.basicFunction(
"",
[
"if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId)) {",
`if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId)) {`,
Template.indent([
"installedChunkData = installedChunks[chunkId];",
"if(installedChunkData !== 0) installedChunks[chunkId] = undefined;",
@ -173,7 +174,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
"chunkId",
"chunkPreloadData",
[
"if(!Object.prototype.hasOwnProperty.call(installedChunks, chunkId) || installedChunks[chunkId] === undefined) {",
`if(!${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) || installedChunks[chunkId] === undefined) {`,
Template.indent([
"installedChunks[chunkId] = null;",
linkPreload.call("", chunk),
@ -202,7 +203,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
? Template.asString([
"function prefetchChunk(chunkId) {",
Template.indent([
"if(!Object.prototype.hasOwnProperty.call(installedChunks, chunkId) || installedChunks[chunkId] === undefined) {",
`if(!${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) || installedChunks[chunkId] === undefined) {`,
Template.indent([
"installedChunks[chunkId] = null;",
linkPrefetch.call("", chunk),
@ -251,7 +252,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
[
"for(var moduleId in moreModules) {",
Template.indent([
"if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {",
`if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
Template.indent([
"currentUpdate[moduleId] = moreModules[moduleId];",
"if(currentUpdatedModulesList) currentUpdatedModulesList.push(moduleId);"
@ -310,7 +311,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
"currentUpdateRuntime = [];",
"currentUpdatedModulesList = updatedModulesList;",
runtimeTemplate.forEach("chunkId", "chunkIds", [
"if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId] !== undefined) {",
`if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) && installedChunks[chunkId] !== undefined) {`,
Template.indent(["promises.push(loadUpdateChunk(chunkId));"]),
"}",
"currentUpdateChunks[chunkId] = true;"
@ -414,7 +415,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
"for(;i < chunkIds.length; i++) {",
Template.indent([
"chunkId = chunkIds[i];",
"if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {",
`if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) && installedChunks[chunkId]) {`,
Template.indent("resolves.push(installedChunks[chunkId][0]);"),
"}",
"installedChunks[chunkId] = 0;"
@ -422,7 +423,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
"}",
"for(moduleId in moreModules) {",
Template.indent([
"if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {",
`if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
Template.indent(
`${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`
),

View File

@ -145,6 +145,7 @@ class JsonpTemplatePlugin {
linkPreload,
linkPrefetch
} = JsonpTemplatePlugin.getCompilationHooks(compilation);
const { runtimeTemplate } = compilation;
jsonpScript.tap("JsonpTemplatePlugin", (_, chunk, hash) => {
const {
@ -178,9 +179,13 @@ class JsonpTemplatePlugin {
: "",
"// create error before stack unwound to get useful stacktrace later",
"var error = new Error();",
"onScriptComplete = function (event) {",
runtimeTemplate.supportsArrowFunction()
? "onScriptComplete = event => {"
: "onScriptComplete = function (event) {",
Template.indent([
"onScriptComplete = function() {};",
runtimeTemplate.supportsArrowFunction()
? "onScriptComplete = _ => _;"
: "onScriptComplete = function() {};",
"// avoid mem leaks in IE.",
"script.onerror = script.onload = null;",
"clearTimeout(timeout);",
@ -198,11 +203,17 @@ class JsonpTemplatePlugin {
"}"
]),
"};",
"var timeout = setTimeout(function(){",
Template.indent([
"onScriptComplete({ type: 'timeout', target: script });"
]),
`}, ${chunkLoadTimeout});`,
...(runtimeTemplate.supportsArrowFunction()
? [
`var timeout = setTimeout(_ => onScriptComplete({ type: 'timeout', target: script }), ${chunkLoadTimeout});`
]
: [
"var timeout = setTimeout(function(){",
Template.indent([
"onScriptComplete({ type: 'timeout', target: script });"
]),
`}, ${chunkLoadTimeout});`
]),
"script.onerror = script.onload = onScriptComplete;"
]);
});

View File

@ -12,6 +12,7 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule {
constructor(runtimeRequirements) {
super("importScripts chunk loading", 10);
this.runtimeRequirements = runtimeRequirements;
this.runtimeRequirements.add(RuntimeGlobals.hasOwnProperty);
}
/**
@ -57,7 +58,7 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule {
Template.indent([
"for(var moduleId in moreModules) {",
Template.indent([
"if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {",
`if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
Template.indent(
`${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`
),
@ -95,7 +96,7 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule {
Template.indent([
"for(var moduleId in moreModules) {",
Template.indent([
"if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {",
`if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
Template.indent([
"currentUpdate[moduleId] = moreModules[moduleId];",
"if(updatedModulesList) updatedModulesList.push(moduleId);"

View File

@ -217,10 +217,10 @@ describe("Stats", () => {
"comparedForEmit": false,
"emitted": true,
"info": Object {
"size": 2044,
"size": 1940,
},
"name": "entryB.js",
"size": 2044,
"size": 1940,
},
],
"assetsByChunkName": Object {

File diff suppressed because it is too large Load Diff