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 HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
|
||||
const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImportSideEffectDependency");
|
||||
const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency");
|
||||
const JavascriptParser = require("../javascript/JavascriptParser");
|
||||
const {
|
||||
getMakeDeferredNamespaceModeFromExportsType,
|
||||
|
@ -1832,6 +1833,25 @@ ${defineGetters}`
|
|||
if (!source) continue;
|
||||
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>[]} */
|
||||
|
@ -1855,10 +1875,19 @@ ${defineGetters}`
|
|||
for (const dep of info.module.dependencies) {
|
||||
if (
|
||||
!(/** @type {HarmonyImportDependency} */ (dep).defer) &&
|
||||
dep instanceof HarmonyImportSideEffectDependency
|
||||
(dep instanceof HarmonyImportSideEffectDependency ||
|
||||
dep instanceof HarmonyImportSpecifierDependency)
|
||||
) {
|
||||
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)) {
|
||||
const deferredModuleInfo = /** @type {ExternalModuleInfo} */ (
|
||||
modulesWithInfo.find(
|
||||
|
@ -1887,6 +1916,8 @@ ${defineGetters}`
|
|||
break;
|
||||
}
|
||||
case "external": {
|
||||
// deferred case is handled in the "const info of modulesWithInfo" loop above
|
||||
if (!info.deferred) {
|
||||
result.add(
|
||||
`\n// EXTERNAL MODULE: ${info.module.readableIdentifier(
|
||||
requestShortener
|
||||
|
@ -1906,22 +1937,9 @@ ${defineGetters}`
|
|||
isConditional = true;
|
||||
result.add(`if (${condition}) {\n`);
|
||||
}
|
||||
const moduleId = JSON.stringify(chunkGraph.getModuleId(info.module));
|
||||
if (info.deferred) {
|
||||
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.
|
||||
[]
|
||||
const moduleId = JSON.stringify(
|
||||
chunkGraph.getModuleId(info.module)
|
||||
);
|
||||
result.add(`var ${info.deferredName} = ${loader};`);
|
||||
name = info.deferredName;
|
||||
} else {
|
||||
result.add(`var ${info.name} = __webpack_require__(${moduleId});`);
|
||||
name = info.name;
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ class MakeDeferredNamespaceObjectRuntimeModule extends HelperRuntimeModule {
|
|||
])},`,
|
||||
`ownKeys: ${runtimeTemplate.basicFunction("", [
|
||||
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;"
|
||||
])},`,
|
||||
`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