Skip to content

Commit 951150d

Browse files
Merge branch 'main' into cursor/module-federation-webworker-bug-09a5
2 parents 2a70144 + 5a4f503 commit 951150d

34 files changed

+1176
-549
lines changed

.changeset/cozy-worlds-drum.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@module-federation/manifest': patch
3+
---
4+
5+
fix(manifest): record split expose chunk assets

.changeset/fair-eels-grab.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@module-federation/metro': patch
3+
---
4+
5+
fix Metro Windows compatibility by normalizing path handling and source URL generation across absolute and relative entry paths, and tighten expose key resolution to avoid incorrect extension fallback matches.

.changeset/pink-ravens-glow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@module-federation/rspress-plugin': patch
3+
---
4+
5+
fix(rspress-plugin): auto infer environment

apps/rslib-module/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"http-server": "^14.1.1",
2929
"react": "^18.3.1",
3030
"react-dom": "^18.3.1",
31-
"storybook": "^8.3.6",
31+
"storybook": "^8.6.17",
3232
"storybook-react-rsbuild": "^1.0.1",
3333
"storybook-addon-rslib": "^1.0.1"
3434
},

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@
166166
"rambda": "7.5.0",
167167
"regenerator-runtime": "0.14.1",
168168
"sharp": "^0.33.4",
169-
"storybook": "9.0.9",
169+
"storybook": "8.6.17",
170170
"tapable": "2.2.1",
171171
"typedoc": "0.25.8",
172172
"undici": "7.18.2",
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
const fs = __non_webpack_require__('fs');
2+
const path = __non_webpack_require__('path');
3+
4+
const statsPath = path.join(__dirname, 'mf-stats.json');
5+
const stats = JSON.parse(fs.readFileSync(statsPath, 'utf-8'));
6+
7+
it('should have one expose entry', () => {
8+
expect(stats.exposes).toHaveLength(1);
9+
expect(stats.exposes[0].path).toBe('./expose-a');
10+
});
11+
12+
it('should collect all expose chunk assets even when split by splitChunks.maxSize', () => {
13+
const syncFiles = stats.exposes[0].assets.js.sync;
14+
15+
// Discover every JS file webpack actually emitted for this expose chunk.
16+
// Split chunks produced by maxSize are named "__federation_expose_expose_a-<hash>.js",
17+
// so we match on the expose chunk name prefix.
18+
const exposeChunkPrefix = '__federation_expose_expose_a';
19+
const emittedExposeFiles = fs
20+
.readdirSync(__dirname)
21+
.filter((f) => f.startsWith(exposeChunkPrefix) && f.endsWith('.js'));
22+
23+
// At least the primary expose chunk must exist
24+
expect(emittedExposeFiles.length).toBeGreaterThanOrEqual(1);
25+
26+
// Every emitted expose chunk file must appear in the stats assets.
27+
// This verifies the fix: without it, split chunks named
28+
// "__federation_expose_expose_a-<hash>" would be missed by the direct
29+
// Map lookup in StatsManager._getModuleAssets.
30+
expect(syncFiles.sort()).toEqual(
31+
expect.arrayContaining(emittedExposeFiles.sort()),
32+
);
33+
});
34+
35+
it('should have multiple sync JS files when splitting actually occurred', () => {
36+
const syncFiles = stats.exposes[0].assets.js.sync;
37+
const exposeChunkPrefix = '__federation_expose_expose_a';
38+
const splitChunkFiles = syncFiles.filter((f) =>
39+
f.startsWith(exposeChunkPrefix),
40+
);
41+
42+
// With minSize:0 and maxSize:100 and two modules each >100 bytes,
43+
// webpack must have produced more than one expose-related chunk.
44+
expect(splitChunkFiles.length).toBeGreaterThan(1);
45+
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { dataA, extraA } from './part-a';
2+
export { dataB, extraB } from './part-b';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Part A — content intentionally sized to participate in maxSize splitting
2+
export const dataA = 'part-a-primary-export-value-for-split-chunks-test';
3+
export const extraA = 'part-a-secondary-export-value-for-split-chunks-test';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Part B — content intentionally sized to participate in maxSize splitting
2+
export const dataB = 'part-b-primary-export-value-for-split-chunks-test';
3+
export const extraB = 'part-b-secondary-export-value-for-split-chunks-test';
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const { ModuleFederationPlugin } = require('../../../../dist/src');
2+
3+
module.exports = {
4+
mode: 'production',
5+
optimization: {
6+
chunkIds: 'named',
7+
moduleIds: 'named',
8+
splitChunks: {
9+
cacheGroups: {
10+
'expose-a': {
11+
chunks: /__federation_expose_expose_a/,
12+
minSize: 0,
13+
maxSize: 100,
14+
name: '__federation_expose_expose_a',
15+
},
16+
},
17+
},
18+
},
19+
output: {
20+
publicPath: '/',
21+
},
22+
plugins: [
23+
new ModuleFederationPlugin({
24+
name: 'manifest_split_chunks',
25+
filename: 'container.js',
26+
library: { type: 'commonjs-module' },
27+
exposes: {
28+
'./expose-a': './module.js',
29+
},
30+
manifest: true,
31+
}),
32+
],
33+
};

0 commit comments

Comments
 (0)