mirror of https://github.com/webpack/webpack.git
fix: deferred modules define order and transitive deferred module not emitted correctly in concatenated modules
This commit is contained in:
parent
73cecf5e78
commit
c647cf193c
|
@ -23,6 +23,7 @@ const Template = require("../Template");
|
||||||
const { DEFAULTS } = require("../config/defaults");
|
const { DEFAULTS } = require("../config/defaults");
|
||||||
const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
|
const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
|
||||||
const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImportSideEffectDependency");
|
const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImportSideEffectDependency");
|
||||||
|
const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency");
|
||||||
const JavascriptParser = require("../javascript/JavascriptParser");
|
const JavascriptParser = require("../javascript/JavascriptParser");
|
||||||
const {
|
const {
|
||||||
getMakeDeferredNamespaceModeFromExportsType,
|
getMakeDeferredNamespaceModeFromExportsType,
|
||||||
|
@ -1832,6 +1833,25 @@ ${defineGetters}`
|
||||||
if (!source) continue;
|
if (!source) continue;
|
||||||
result.add(source);
|
result.add(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info.type === "external" && info.deferred) {
|
||||||
|
const moduleId = JSON.stringify(chunkGraph.getModuleId(info.module));
|
||||||
|
const loader = getOptimizedDeferredModule(
|
||||||
|
runtimeTemplate,
|
||||||
|
info.module.getExportsType(
|
||||||
|
moduleGraph,
|
||||||
|
/** @type {BuildMeta} */
|
||||||
|
(this.rootModule.buildMeta).strictHarmonyModule
|
||||||
|
),
|
||||||
|
moduleId,
|
||||||
|
// an async module will opt-out of the concat module optimization.
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
runtimeRequirements.add(RuntimeGlobals.require);
|
||||||
|
result.add(
|
||||||
|
`\n// DEFERRED EXTERNAL MODULE: ${info.module.readableIdentifier(requestShortener)}\nvar ${info.deferredName} = ${loader};`
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {InitFragment<ChunkRenderContext>[]} */
|
/** @type {InitFragment<ChunkRenderContext>[]} */
|
||||||
|
@ -1855,10 +1875,19 @@ ${defineGetters}`
|
||||||
for (const dep of info.module.dependencies) {
|
for (const dep of info.module.dependencies) {
|
||||||
if (
|
if (
|
||||||
!(/** @type {HarmonyImportDependency} */ (dep).defer) &&
|
!(/** @type {HarmonyImportDependency} */ (dep).defer) &&
|
||||||
dep instanceof HarmonyImportSideEffectDependency
|
(dep instanceof HarmonyImportSideEffectDependency ||
|
||||||
|
dep instanceof HarmonyImportSpecifierDependency)
|
||||||
) {
|
) {
|
||||||
const referredModule = moduleGraph.getModule(dep);
|
const referredModule = moduleGraph.getModule(dep);
|
||||||
if (!referredModule) continue;
|
if (!referredModule) {
|
||||||
|
if (dep instanceof HarmonyImportSideEffectDependency) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"Deferred module used, but no module in the graph."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (moduleGraph.isDeferred(referredModule)) {
|
if (moduleGraph.isDeferred(referredModule)) {
|
||||||
const deferredModuleInfo = /** @type {ExternalModuleInfo} */ (
|
const deferredModuleInfo = /** @type {ExternalModuleInfo} */ (
|
||||||
modulesWithInfo.find(
|
modulesWithInfo.find(
|
||||||
|
@ -1887,41 +1916,30 @@ ${defineGetters}`
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "external": {
|
case "external": {
|
||||||
result.add(
|
// deferred case is handled in the "const info of modulesWithInfo" loop above
|
||||||
`\n// EXTERNAL MODULE: ${info.module.readableIdentifier(
|
if (!info.deferred) {
|
||||||
requestShortener
|
result.add(
|
||||||
)}\n`
|
`\n// EXTERNAL MODULE: ${info.module.readableIdentifier(
|
||||||
);
|
requestShortener
|
||||||
runtimeRequirements.add(RuntimeGlobals.require);
|
)}\n`
|
||||||
const { runtimeCondition } =
|
);
|
||||||
/** @type {ExternalModuleInfo | ReferenceToModuleInfo} */
|
runtimeRequirements.add(RuntimeGlobals.require);
|
||||||
(rawInfo);
|
const { runtimeCondition } =
|
||||||
const condition = runtimeTemplate.runtimeConditionExpression({
|
/** @type {ExternalModuleInfo | ReferenceToModuleInfo} */
|
||||||
chunkGraph,
|
(rawInfo);
|
||||||
runtimeCondition,
|
const condition = runtimeTemplate.runtimeConditionExpression({
|
||||||
runtime,
|
chunkGraph,
|
||||||
runtimeRequirements
|
runtimeCondition,
|
||||||
});
|
runtime,
|
||||||
if (condition !== "true") {
|
runtimeRequirements
|
||||||
isConditional = true;
|
});
|
||||||
result.add(`if (${condition}) {\n`);
|
if (condition !== "true") {
|
||||||
}
|
isConditional = true;
|
||||||
const moduleId = JSON.stringify(chunkGraph.getModuleId(info.module));
|
result.add(`if (${condition}) {\n`);
|
||||||
if (info.deferred) {
|
}
|
||||||
const loader = getOptimizedDeferredModule(
|
const moduleId = JSON.stringify(
|
||||||
runtimeTemplate,
|
chunkGraph.getModuleId(info.module)
|
||||||
info.module.getExportsType(
|
|
||||||
moduleGraph,
|
|
||||||
/** @type {BuildMeta} */
|
|
||||||
(this.rootModule.buildMeta).strictHarmonyModule
|
|
||||||
),
|
|
||||||
moduleId,
|
|
||||||
// an async module will opt-out of the concat module optimization.
|
|
||||||
[]
|
|
||||||
);
|
);
|
||||||
result.add(`var ${info.deferredName} = ${loader};`);
|
|
||||||
name = info.deferredName;
|
|
||||||
} else {
|
|
||||||
result.add(`var ${info.name} = __webpack_require__(${moduleId});`);
|
result.add(`var ${info.name} = __webpack_require__(${moduleId});`);
|
||||||
name = info.name;
|
name = info.name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,7 @@ class MakeDeferredNamespaceObjectRuntimeModule extends HelperRuntimeModule {
|
||||||
])},`,
|
])},`,
|
||||||
`ownKeys: ${runtimeTemplate.basicFunction("", [
|
`ownKeys: ${runtimeTemplate.basicFunction("", [
|
||||||
init,
|
init,
|
||||||
`var keys = Reflect.ownKeys(ns).filter(${runtimeTemplate.expressionFunction('x !== "then"', "x")}).concat([Symbol.toStringTag]);`,
|
`var keys = Reflect.ownKeys(ns).filter(${runtimeTemplate.expressionFunction('x !== "then" && x !== Symbol.toStringTag', "x")}).concat([Symbol.toStringTag]);`,
|
||||||
"return keys;"
|
"return keys;"
|
||||||
])},`,
|
])},`,
|
||||||
`getOwnPropertyDescriptor: ${runtimeTemplate.basicFunction("_, name", [
|
`getOwnPropertyDescriptor: ${runtimeTemplate.basicFunction("_, name", [
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { a } from 'mod'
|
||||||
|
|
||||||
|
Object.keys(a).forEach(() => { })
|
|
@ -0,0 +1,3 @@
|
||||||
|
import defer * as m from 'mod'
|
||||||
|
|
||||||
|
Object.keys(m).forEach(() => {})
|
|
@ -0,0 +1,3 @@
|
||||||
|
it('should compile and load', () => {
|
||||||
|
require('./main.js');
|
||||||
|
})
|
|
@ -0,0 +1,2 @@
|
||||||
|
import './a'
|
||||||
|
import './b'
|
1
test/configCases/defer-import/concatenated-1/node_modules/mod/index.js
generated
vendored
Normal file
1
test/configCases/defer-import/concatenated-1/node_modules/mod/index.js
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { a } from './re-export'
|
5
test/configCases/defer-import/concatenated-1/node_modules/mod/package.json
generated
vendored
Normal file
5
test/configCases/defer-import/concatenated-1/node_modules/mod/package.json
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"sideEffects": false,
|
||||||
|
"main": "./index.js",
|
||||||
|
"name": "mod"
|
||||||
|
}
|
3
test/configCases/defer-import/concatenated-1/node_modules/mod/re-export.js
generated
vendored
Normal file
3
test/configCases/defer-import/concatenated-1/node_modules/mod/re-export.js
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export function a() {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/** @type {import("../../../../types").Configuration} */
|
||||||
|
module.exports = {
|
||||||
|
target: [`async-node${process.versions.node.split(".").map(Number)[0]}`],
|
||||||
|
optimization: {
|
||||||
|
concatenateModules: true
|
||||||
|
},
|
||||||
|
experiments: {
|
||||||
|
deferImport: true
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
import defer * as mod from 'mod'
|
||||||
|
|
||||||
|
export function b() {
|
||||||
|
mod.fn()
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
it('should compile and load', () => {
|
||||||
|
require('./main.js');
|
||||||
|
})
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { fn } from 'mod'
|
||||||
|
import { b } from './a'
|
||||||
|
|
||||||
|
fn()
|
||||||
|
b()
|
1
test/configCases/defer-import/concatenated-2/node_modules/mod/index.js
generated
vendored
Normal file
1
test/configCases/defer-import/concatenated-2/node_modules/mod/index.js
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { fn } from './re-export'
|
5
test/configCases/defer-import/concatenated-2/node_modules/mod/package.json
generated
vendored
Normal file
5
test/configCases/defer-import/concatenated-2/node_modules/mod/package.json
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"sideEffects": false,
|
||||||
|
"main": "./index.js",
|
||||||
|
"name": "mod"
|
||||||
|
}
|
1
test/configCases/defer-import/concatenated-2/node_modules/mod/re-export.js
generated
vendored
Normal file
1
test/configCases/defer-import/concatenated-2/node_modules/mod/re-export.js
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export function fn() {}
|
|
@ -0,0 +1,12 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/** @type {import("../../../../types").Configuration} */
|
||||||
|
module.exports = {
|
||||||
|
target: [`async-node${process.versions.node.split(".").map(Number)[0]}`],
|
||||||
|
optimization: {
|
||||||
|
concatenateModules: true
|
||||||
|
},
|
||||||
|
experiments: {
|
||||||
|
deferImport: true
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue