fix(esm): fix the import of missing dependency chunks (#19782)

This commit is contained in:
Xiao 2025-08-11 19:52:42 +08:00 committed by GitHub
parent 4fdb0e16eb
commit a87f569b92
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 308 additions and 27 deletions

View File

@ -168,9 +168,10 @@ class ModuleChunkFormatPlugin {
PLUGIN_NAME,
(modules, _lastModule, renderContext) => {
const { chunk, chunkGraph } = renderContext;
if (!chunk.hasRuntime()) {
return modules;
}
if (
chunkGraph.getNumberOfEntryModules(chunk) > 0 &&
chunk.hasRuntime()
) {
const entryDependentChunks =
chunkGraph.getChunkEntryDependentChunksIterable(chunk);
const sourceWithDependentChunks = withDependentChunks(
@ -190,6 +191,8 @@ class ModuleChunkFormatPlugin {
source.add(modules);
return source;
}
return modules;
}
);
hooks.renderChunk.tap(PLUGIN_NAME, (modules, renderContext) => {
const { chunk, chunkGraph, runtimeTemplate } = renderContext;
@ -238,9 +241,6 @@ class ModuleChunkFormatPlugin {
}
const final = i + 1 === entries.length;
const moduleId = chunkGraph.getModuleId(module);
const entryDependentChunks = /** @type {Set<Chunk>} */ (
chunkGraph.getChunkEntryDependentChunksIterable(chunk)
);
const chunks = getAllChunks(
/** @type {Entrypoint} */ (entrypoint),
/** @type {Chunk} */ (runtimeChunk),
@ -248,10 +248,7 @@ class ModuleChunkFormatPlugin {
);
const processChunks = new Set();
for (const _chunk of chunks) {
if (
loadedChunks.has(_chunk) ||
entryDependentChunks.has(_chunk)
) {
if (loadedChunks.has(_chunk)) {
continue;
}
loadedChunks.add(_chunk);

View File

@ -0,0 +1 @@
export default "common";

View File

@ -0,0 +1,6 @@
import common from "./common";
it("should compile", () => {
expect(common).toBe("common");
});
export default "main";

View File

@ -0,0 +1 @@
export default "separate";

View File

@ -0,0 +1,7 @@
"use strict";
module.exports = {
findBundle() {
return ["./main.mjs"];
}
};

View File

@ -0,0 +1,41 @@
"use strict";
const EntryPlugin = require("../../../../").EntryPlugin;
/** @type {import("../../../../types").Configuration} */
module.exports = () => ({
devtool: false,
mode: "development",
entry: {
main: {
import: "./index.js",
dependOn: "shared"
},
shared: "./common.js"
},
output: {
filename: "[name].mjs",
library: {
type: "module"
}
},
target: ["web", "es2020"],
experiments: {
outputModule: true
},
optimization: {
minimize: false,
runtimeChunk: false,
splitChunks: {
cacheGroups: {
separate: {
test: /separate/,
chunks: "all",
filename: "separate.mjs",
enforce: true
}
}
}
},
plugins: [new EntryPlugin(__dirname, "./separate.js", "main")]
});

View File

@ -0,0 +1,2 @@
import separate from "./separate";
export default separate;

View File

@ -0,0 +1,7 @@
import separate from "./separate";
import common from "./common";
it("should compile", () => {
expect(separate).toBe("separate");
expect(common).toBe("separate");
});
export default "main";

View File

@ -0,0 +1 @@
export default "separate";

View File

@ -0,0 +1,7 @@
"use strict";
module.exports = {
findBundle() {
return ["./main.mjs"];
}
};

View File

@ -0,0 +1,38 @@
"use strict";
/** @type {import("../../../../types").Configuration} */
module.exports = () => ({
devtool: false,
mode: "development",
entry: {
main: {
import: "./index.js",
dependOn: "shared"
},
shared: "./common.js"
},
output: {
filename: "[name].mjs",
library: {
type: "module"
}
},
target: ["web", "es2020"],
experiments: {
outputModule: true
},
optimization: {
minimize: false,
runtimeChunk: false,
splitChunks: {
cacheGroups: {
separate: {
test: /separate/,
chunks: "all",
filename: "separate.mjs",
enforce: true
}
}
}
}
});

View File

@ -0,0 +1 @@
export default "common";

View File

@ -0,0 +1,8 @@
import common from "./common";
import separate from "./separate";
it("should compile", () => {
expect(common).toBe("common");
expect(separate).toBe("separate");
});
export default "main";

View File

@ -0,0 +1 @@
export default "separate";

View File

@ -0,0 +1,7 @@
"use strict";
module.exports = {
findBundle() {
return ["./main.mjs"];
}
};

View File

@ -0,0 +1,38 @@
"use strict";
/** @type {import("../../../../types").Configuration} */
module.exports = () => ({
devtool: false,
mode: "development",
entry: {
main: {
import: "./index.js",
dependOn: "shared"
},
shared: "./common.js"
},
output: {
filename: "[name].mjs",
library: {
type: "module"
}
},
target: ["web", "es2020"],
experiments: {
outputModule: true
},
optimization: {
minimize: false,
runtimeChunk: "single",
splitChunks: {
cacheGroups: {
separate: {
test: /separate/,
chunks: "all",
filename: "separate.mjs",
enforce: true
}
}
}
}
});

View File

@ -0,0 +1 @@
export default "common";

View File

@ -0,0 +1,4 @@
it("should compile", () => {
expect("common").toBe("common");
});
export default "main";

View File

@ -0,0 +1,2 @@
import common from "./common";
export default common;

View File

@ -0,0 +1,7 @@
"use strict";
module.exports = {
findBundle() {
return ["./main.mjs"];
}
};

View File

@ -0,0 +1,45 @@
"use strict";
const EntryPlugin = require("../../../../").EntryPlugin;
/** @type {import("../../../../types").Configuration} */
module.exports = () => ({
devtool: false,
mode: "development",
entry: {
main: {
import: "./index.js"
}
},
output: {
filename: "[name].mjs",
library: {
type: "module"
}
},
target: ["web", "es2020"],
experiments: {
outputModule: true
},
optimization: {
minimize: false,
runtimeChunk: false,
splitChunks: {
cacheGroups: {
separate: {
test: /separate/,
chunks: "all",
filename: "separate.mjs",
enforce: true
},
common: {
test: /common/,
chunks: "all",
filename: "common.mjs",
enforce: true
}
}
}
},
plugins: [new EntryPlugin(__dirname, "./separate.js", "main")]
});

View File

@ -0,0 +1 @@
export default "common";

View File

@ -0,0 +1,4 @@
it("should compile", () => {
expect("common").toBe("common");
});
export default "main";

View File

@ -0,0 +1,2 @@
import common from "./common";
export default common;

View File

@ -0,0 +1,7 @@
"use strict";
module.exports = {
findBundle() {
return ["./main.mjs"];
}
};

View File

@ -0,0 +1,45 @@
"use strict";
const EntryPlugin = require("../../../../").EntryPlugin;
/** @type {import("../../../../types").Configuration} */
module.exports = () => ({
devtool: false,
mode: "development",
entry: {
main: {
import: "./index.js"
}
},
output: {
filename: "[name].mjs",
library: {
type: "module"
}
},
target: ["web", "es2020"],
experiments: {
outputModule: true
},
optimization: {
minimize: false,
runtimeChunk: "single",
splitChunks: {
cacheGroups: {
separate: {
test: /separate/,
chunks: "all",
filename: "separate.mjs",
enforce: true
},
common: {
test: /common/,
chunks: "all",
filename: "common.mjs",
enforce: true
}
}
}
},
plugins: [new EntryPlugin(__dirname, "./separate.js", "main")]
});