mirror of https://github.com/webpack/webpack.git
perf: fix regression in module concatenation
This commit is contained in:
parent
4065bddc9d
commit
aeab4c5ac1
|
@ -11,6 +11,7 @@ const ModuleGraphConnection = require("./ModuleGraphConnection");
|
||||||
const SortableSet = require("./util/SortableSet");
|
const SortableSet = require("./util/SortableSet");
|
||||||
const WeakTupleMap = require("./util/WeakTupleMap");
|
const WeakTupleMap = require("./util/WeakTupleMap");
|
||||||
const { sortWithSourceOrder } = require("./util/comparators");
|
const { sortWithSourceOrder } = require("./util/comparators");
|
||||||
|
const memoize = require("./util/memoize");
|
||||||
|
|
||||||
/** @typedef {import("./Compilation").ModuleMemCaches} ModuleMemCaches */
|
/** @typedef {import("./Compilation").ModuleMemCaches} ModuleMemCaches */
|
||||||
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
|
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
|
||||||
|
@ -24,6 +25,10 @@ const { sortWithSourceOrder } = require("./util/comparators");
|
||||||
/** @typedef {import("./dependencies/HarmonyImportSpecifierDependency")} HarmonyImportSpecifierDependency */
|
/** @typedef {import("./dependencies/HarmonyImportSpecifierDependency")} HarmonyImportSpecifierDependency */
|
||||||
/** @typedef {import("./util/comparators").DependencySourceOrder} DependencySourceOrder */
|
/** @typedef {import("./util/comparators").DependencySourceOrder} DependencySourceOrder */
|
||||||
|
|
||||||
|
const getCommonJsSelfReferenceDependency = memoize(() =>
|
||||||
|
require("./dependencies/CommonJsSelfReferenceDependency")
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @callback OptimizationBailoutFunction
|
* @callback OptimizationBailoutFunction
|
||||||
* @param {RequestShortener} requestShortener
|
* @param {RequestShortener} requestShortener
|
||||||
|
@ -840,8 +845,7 @@ class ModuleGraph {
|
||||||
for (const connection of connections) {
|
for (const connection of connections) {
|
||||||
if (
|
if (
|
||||||
!connection.dependency ||
|
!connection.dependency ||
|
||||||
connection.dependency instanceof
|
connection.dependency instanceof getCommonJsSelfReferenceDependency()
|
||||||
require("./dependencies/CommonJsSelfReferenceDependency")
|
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -384,6 +384,7 @@ const applyExperimentsDefaults = (
|
||||||
D(experiments, "lazyCompilation", undefined);
|
D(experiments, "lazyCompilation", undefined);
|
||||||
D(experiments, "buildHttp", undefined);
|
D(experiments, "buildHttp", undefined);
|
||||||
D(experiments, "cacheUnaffected", experiments.futureDefaults);
|
D(experiments, "cacheUnaffected", experiments.futureDefaults);
|
||||||
|
D(experiments, "deferImport", false);
|
||||||
F(experiments, "css", () => (experiments.futureDefaults ? true : undefined));
|
F(experiments, "css", () => (experiments.futureDefaults ? true : undefined));
|
||||||
|
|
||||||
// TODO webpack 6: remove this. topLevelAwait should be enabled by default
|
// TODO webpack 6: remove this. topLevelAwait should be enabled by default
|
||||||
|
|
|
@ -77,13 +77,16 @@ module.exports = class HarmonyExportDependencyParserPlugin {
|
||||||
clearDep.loc = /** @type {DependencyLocation} */ (statement.loc);
|
clearDep.loc = /** @type {DependencyLocation} */ (statement.loc);
|
||||||
clearDep.loc.index = -1;
|
clearDep.loc.index = -1;
|
||||||
parser.state.module.addPresentationalDependency(clearDep);
|
parser.state.module.addPresentationalDependency(clearDep);
|
||||||
const { defer } = getImportMode(parser, statement);
|
let defer = false;
|
||||||
if (defer) {
|
if (this.deferImport) {
|
||||||
const error = new WebpackError(
|
({ defer } = getImportMode(parser, statement));
|
||||||
"Deferred re-export (`export defer * as namespace from '...'`) is not a part of the Import Defer proposal.\nUse the following code instead:\n import defer * as namespace from '...';\n export { namespace };"
|
if (defer) {
|
||||||
);
|
const error = new WebpackError(
|
||||||
error.loc = statement.loc || undefined;
|
"Deferred re-export (`export defer * as namespace from '...'`) is not a part of the Import Defer proposal.\nUse the following code instead:\n import defer * as namespace from '...';\n export { namespace };"
|
||||||
parser.state.current.addError(error);
|
);
|
||||||
|
error.loc = statement.loc || undefined;
|
||||||
|
parser.state.current.addError(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const sideEffectDep = new HarmonyImportSideEffectDependency(
|
const sideEffectDep = new HarmonyImportSideEffectDependency(
|
||||||
/** @type {string} */ (source),
|
/** @type {string} */ (source),
|
||||||
|
@ -202,7 +205,9 @@ module.exports = class HarmonyExportDependencyParserPlugin {
|
||||||
parser.state.harmonyStarExports || new HarmonyStarExportsList();
|
parser.state.harmonyStarExports || new HarmonyStarExportsList();
|
||||||
}
|
}
|
||||||
const attributes = getImportAttributes(statement);
|
const attributes = getImportAttributes(statement);
|
||||||
const { defer } = getImportMode(parser, statement);
|
const defer = this.deferImport
|
||||||
|
? getImportMode(parser, statement).defer
|
||||||
|
: false;
|
||||||
const dep = new HarmonyExportImportedSpecifierDependency(
|
const dep = new HarmonyExportImportedSpecifierDependency(
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
(source),
|
(source),
|
||||||
|
|
|
@ -124,17 +124,20 @@ module.exports = class HarmonyImportDependencyParserPlugin {
|
||||||
parser.state.module.addPresentationalDependency(clearDep);
|
parser.state.module.addPresentationalDependency(clearDep);
|
||||||
parser.unsetAsiPosition(/** @type {Range} */ (statement.range)[1]);
|
parser.unsetAsiPosition(/** @type {Range} */ (statement.range)[1]);
|
||||||
const attributes = getImportAttributes(statement);
|
const attributes = getImportAttributes(statement);
|
||||||
const { defer } = getImportMode(parser, statement);
|
let defer = false;
|
||||||
if (
|
if (this.deferImport) {
|
||||||
defer &&
|
({ defer } = getImportMode(parser, statement));
|
||||||
(statement.specifiers.length !== 1 ||
|
if (
|
||||||
statement.specifiers[0].type !== "ImportNamespaceSpecifier")
|
defer &&
|
||||||
) {
|
(statement.specifiers.length !== 1 ||
|
||||||
const error = new WebpackError(
|
statement.specifiers[0].type !== "ImportNamespaceSpecifier")
|
||||||
"Deferred import can only be used with `import * as namespace from '...'` syntax."
|
) {
|
||||||
);
|
const error = new WebpackError(
|
||||||
error.loc = statement.loc || undefined;
|
"Deferred import can only be used with `import * as namespace from '...'` syntax."
|
||||||
parser.state.current.addError(error);
|
);
|
||||||
|
error.loc = statement.loc || undefined;
|
||||||
|
parser.state.current.addError(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const sideEffectDep = new HarmonyImportSideEffectDependency(
|
const sideEffectDep = new HarmonyImportSideEffectDependency(
|
||||||
/** @type {string} */ (source),
|
/** @type {string} */ (source),
|
||||||
|
@ -150,7 +153,9 @@ module.exports = class HarmonyImportDependencyParserPlugin {
|
||||||
PLUGIN_NAME,
|
PLUGIN_NAME,
|
||||||
(statement, source, id, name) => {
|
(statement, source, id, name) => {
|
||||||
const ids = id === null ? [] : [id];
|
const ids = id === null ? [] : [id];
|
||||||
const { defer } = getImportMode(parser, statement);
|
const defer = this.deferImport
|
||||||
|
? getImportMode(parser, statement).defer
|
||||||
|
: false;
|
||||||
parser.tagVariable(name, harmonySpecifierTag, {
|
parser.tagVariable(name, harmonySpecifierTag, {
|
||||||
name,
|
name,
|
||||||
source,
|
source,
|
||||||
|
@ -391,7 +396,7 @@ module.exports = class HarmonyImportDependencyParserPlugin {
|
||||||
/**
|
/**
|
||||||
* @param {JavascriptParser} parser parser
|
* @param {JavascriptParser} parser parser
|
||||||
* @param {ExportNamedDeclaration | ExportAllDeclaration | ImportDeclaration} node node
|
* @param {ExportNamedDeclaration | ExportAllDeclaration | ImportDeclaration} node node
|
||||||
* @returns {{defer: boolean}} import attributes
|
* @returns {{ defer: boolean }} import attributes
|
||||||
*/
|
*/
|
||||||
function getImportMode(parser, node) {
|
function getImportMode(parser, node) {
|
||||||
const result = { defer: "phase" in node && node.phase === "defer" };
|
const result = { defer: "phase" in node && node.phase === "defer" };
|
||||||
|
|
|
@ -945,7 +945,8 @@ class ConcatenatedModule extends Module {
|
||||||
/** @type {Map<Module, RuntimeSpec | true>} */
|
/** @type {Map<Module, RuntimeSpec | true>} */
|
||||||
const existingEntries = new Map();
|
const existingEntries = new Map();
|
||||||
const deferEnabled =
|
const deferEnabled =
|
||||||
this.compilation && this.compilation.options.experiments.deferImport;
|
/** @type {Compilation} */
|
||||||
|
(this.compilation).options.experiments.deferImport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Module} module a module
|
* @param {Module} module a module
|
||||||
|
@ -1712,7 +1713,8 @@ ${defineGetters}`
|
||||||
/** @type {InitFragment<ChunkRenderContext>[]} */
|
/** @type {InitFragment<ChunkRenderContext>[]} */
|
||||||
const chunkInitFragments = [];
|
const chunkInitFragments = [];
|
||||||
const deferEnabled =
|
const deferEnabled =
|
||||||
this.compilation && this.compilation.options.experiments.deferImport;
|
/** @type {Compilation} */
|
||||||
|
(this.compilation).options.experiments.deferImport;
|
||||||
|
|
||||||
// evaluate modules in order
|
// evaluate modules in order
|
||||||
for (const rawInfo of modulesWithInfo) {
|
for (const rawInfo of modulesWithInfo) {
|
||||||
|
|
|
@ -149,6 +149,7 @@ class ModuleConcatenationPlugin {
|
||||||
chunkGraph,
|
chunkGraph,
|
||||||
moduleGraph
|
moduleGraph
|
||||||
};
|
};
|
||||||
|
const deferEnabled = compilation.options.experiments.deferImport;
|
||||||
logger.time("select relevant modules");
|
logger.time("select relevant modules");
|
||||||
for (const module of modules) {
|
for (const module of modules) {
|
||||||
let canBeRoot = true;
|
let canBeRoot = true;
|
||||||
|
@ -223,7 +224,7 @@ class ModuleConcatenationPlugin {
|
||||||
canBeInner = false;
|
canBeInner = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moduleGraph.isDeferred(module)) {
|
if (deferEnabled && moduleGraph.isDeferred(module)) {
|
||||||
setInnerBailoutReason(module, "Module is deferred");
|
setInnerBailoutReason(module, "Module is deferred");
|
||||||
canBeInner = false;
|
canBeInner = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@ describe("snapshots", () => {
|
||||||
"buildHttp": undefined,
|
"buildHttp": undefined,
|
||||||
"cacheUnaffected": false,
|
"cacheUnaffected": false,
|
||||||
"css": undefined,
|
"css": undefined,
|
||||||
|
"deferImport": false,
|
||||||
"futureDefaults": false,
|
"futureDefaults": false,
|
||||||
"layers": false,
|
"layers": false,
|
||||||
"lazyCompilation": undefined,
|
"lazyCompilation": undefined,
|
||||||
|
@ -1804,15 +1805,15 @@ describe("snapshots", () => {
|
||||||
{ optimization: { runtimeChunk: "single" } },
|
{ optimization: { runtimeChunk: "single" } },
|
||||||
(e) =>
|
(e) =>
|
||||||
e.toMatchInlineSnapshot(`
|
e.toMatchInlineSnapshot(`
|
||||||
- Expected
|
- Expected
|
||||||
+ Received
|
+ Received
|
||||||
|
|
||||||
@@ ... @@
|
@@ ... @@
|
||||||
- "runtimeChunk": false,
|
- "runtimeChunk": false,
|
||||||
+ "runtimeChunk": Object {
|
+ "runtimeChunk": Object {
|
||||||
+ "name": [Function name],
|
+ "name": [Function name],
|
||||||
+ },
|
+ },
|
||||||
`)
|
`)
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
|
@ -2025,9 +2026,10 @@ describe("snapshots", () => {
|
||||||
@@ ... @@
|
@@ ... @@
|
||||||
- "cacheUnaffected": false,
|
- "cacheUnaffected": false,
|
||||||
- "css": undefined,
|
- "css": undefined,
|
||||||
- "futureDefaults": false,
|
|
||||||
+ "cacheUnaffected": true,
|
+ "cacheUnaffected": true,
|
||||||
+ "css": true,
|
+ "css": true,
|
||||||
|
@@ ... @@
|
||||||
|
- "futureDefaults": false,
|
||||||
+ "futureDefaults": true,
|
+ "futureDefaults": true,
|
||||||
@@ ... @@
|
@@ ... @@
|
||||||
+ },
|
+ },
|
||||||
|
@ -2491,9 +2493,10 @@ describe("snapshots", () => {
|
||||||
@@ ... @@
|
@@ ... @@
|
||||||
- "cacheUnaffected": false,
|
- "cacheUnaffected": false,
|
||||||
- "css": undefined,
|
- "css": undefined,
|
||||||
- "futureDefaults": false,
|
|
||||||
+ "cacheUnaffected": true,
|
+ "cacheUnaffected": true,
|
||||||
+ "css": true,
|
+ "css": true,
|
||||||
|
@@ ... @@
|
||||||
|
- "futureDefaults": false,
|
||||||
+ "futureDefaults": true,
|
+ "futureDefaults": true,
|
||||||
@@ ... @@
|
@@ ... @@
|
||||||
+ },
|
+ },
|
||||||
|
@ -2637,9 +2640,10 @@ describe("snapshots", () => {
|
||||||
@@ ... @@
|
@@ ... @@
|
||||||
- "cacheUnaffected": false,
|
- "cacheUnaffected": false,
|
||||||
- "css": undefined,
|
- "css": undefined,
|
||||||
- "futureDefaults": false,
|
|
||||||
+ "cacheUnaffected": true,
|
+ "cacheUnaffected": true,
|
||||||
+ "css": false,
|
+ "css": false,
|
||||||
|
@@ ... @@
|
||||||
|
- "futureDefaults": false,
|
||||||
+ "futureDefaults": true,
|
+ "futureDefaults": true,
|
||||||
@@ ... @@
|
@@ ... @@
|
||||||
+ },
|
+ },
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
output: {
|
output: {
|
||||||
filename: "[name].js"
|
filename: "[name].js",
|
||||||
|
environment: {
|
||||||
|
nodePrefixForCoreModules: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue