Skip to content

Commit 260f85e

Browse files
authored
fix(esm): ensure dependent chunks are imported before startup & fix duplicate export of 'default'
1 parent 68ce2a7 commit 260f85e

11 files changed

Lines changed: 124 additions & 18 deletions

File tree

lib/esm/ModuleChunkFormatPlugin.js

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -164,24 +164,33 @@ class ModuleChunkFormatPlugin {
164164
return source;
165165
}
166166
};
167-
hooks.renderMain.tap(PLUGIN_NAME, (modules, renderContext) => {
168-
const { chunk, chunkGraph } = renderContext;
169-
const entryDependentChunks =
170-
chunkGraph.getChunkEntryDependentChunksIterable(chunk);
171-
const sourceWithDependentChunks = withDependentChunks(
172-
/** @type {Set<Chunk>} */ (entryDependentChunks),
173-
chunkGraph,
174-
chunk
175-
);
176-
if (!sourceWithDependentChunks) {
177-
return modules;
167+
hooks.renderStartup.tap(
168+
PLUGIN_NAME,
169+
(modules, _lastModule, renderContext) => {
170+
const { chunk, chunkGraph } = renderContext;
171+
if (!chunk.hasRuntime()) {
172+
return modules;
173+
}
174+
const entryDependentChunks =
175+
chunkGraph.getChunkEntryDependentChunksIterable(chunk);
176+
const sourceWithDependentChunks = withDependentChunks(
177+
/** @type {Set<Chunk>} */ (entryDependentChunks),
178+
chunkGraph,
179+
chunk
180+
);
181+
if (!sourceWithDependentChunks) {
182+
return modules;
183+
}
184+
if (modules.size() === 0) {
185+
return sourceWithDependentChunks;
186+
}
187+
const source = new ConcatSource();
188+
source.add(sourceWithDependentChunks);
189+
source.add("\n");
190+
source.add(modules);
191+
return source;
178192
}
179-
const source = new ConcatSource();
180-
source.add(modules);
181-
source.add("\n");
182-
source.add(sourceWithDependentChunks);
183-
return source;
184-
});
193+
);
185194
hooks.renderChunk.tap(PLUGIN_NAME, (modules, renderContext) => {
186195
const { chunk, chunkGraph, runtimeTemplate } = renderContext;
187196
const hotUpdateChunk = chunk instanceof HotUpdateChunk ? chunk : null;

lib/esm/ModuleChunkLoadingPlugin.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,11 @@ class ModuleChunkLoadingPlugin {
7171
.tap(PLUGIN_NAME, handler);
7272
compilation.hooks.runtimeRequirementInTree
7373
.for(RuntimeGlobals.externalInstallChunk)
74-
.tap(PLUGIN_NAME, (chunk, set) => {
74+
.tap(PLUGIN_NAME, (chunk, set, { chunkGraph }) => {
7575
if (!isEnabledForChunk(chunk)) return;
76+
// If a chunk contains an entryModule, all exports are determined by the entryModule.
77+
// The ExportWebpackRequireRuntimeModule is for internal use only and not exposed to users.
78+
if (chunkGraph.getNumberOfEntryModules(chunk) > 0) return;
7679
compilation.addRuntimeModule(
7780
chunk,
7881
new ExportWebpackRequireRuntimeModule()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import value from "./separate";
2+
3+
it("should compile", () => {
4+
expect(value).toBeDefined();
5+
});
6+
7+
export default "main";
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default 42;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
findBundle() {
3+
return ["./main.mjs"];
4+
}
5+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/** @type {import("../../../../").Configuration} */
2+
module.exports = {
3+
mode: "development",
4+
output: {
5+
filename: "[name].mjs",
6+
library: {
7+
type: "module"
8+
}
9+
},
10+
target: ["web", "es2020"],
11+
experiments: {
12+
outputModule: true
13+
},
14+
optimization: {
15+
minimize: false,
16+
runtimeChunk: true,
17+
splitChunks: {
18+
cacheGroups: {
19+
separate: {
20+
test: /separate/,
21+
chunks: "all",
22+
filename: "separate.mjs",
23+
enforce: true
24+
}
25+
}
26+
}
27+
}
28+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import m2 from "./testModule2.js"
2+
3+
it("should compile and evaluate fine", (done) => {
4+
expect(m2()).toBe("m11111111");
5+
done()
6+
});
7+
8+
export default "index";
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
findBundle(i, options) {
3+
return ["main.mjs"];
4+
}
5+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const m1 = "m11111111";
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { m1 } from "./testModule1";
2+
3+
export default function m2() {
4+
return m1;
5+
}

0 commit comments

Comments
 (0)