Skip to content

Commit a50e068

Browse files
authored
refactor: ship manifest (#4130)
1 parent 444db72 commit a50e068

File tree

50 files changed

+913
-272
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+913
-272
lines changed

.changeset/mean-bulldogs-glow.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@module-federation/rsbuild-plugin': patch
3+
'@module-federation/enhanced': patch
4+
'@module-federation/manifest': patch
5+
'@module-federation/modern-js': patch
6+
'@module-federation/rspack': patch
7+
'@module-federation/sdk': patch
8+
---
9+
10+
refactor(manifest): collect assets from build hook

apps/website-new/docs/en/configure/manifest.mdx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
- Type: `boolean | PluginManifestOptions`
44
- Default value: `undefined`
55

6-
Used to control whether to generate a manifest and the corresponding generation configuration.
6+
Controls whether the plugin generates manifest artifacts and how they are produced. When enabled, the plugin emits `mf-manifest.json` and `mf-stats.json` (names can be customized via `fileName`) on every build so that other tools can consume them directly through `processAssets` or from the final build output.
7+
8+
- `mf-stats.json`: captures the full build statistics, including the assets for exposes/shared/remotes, `metaData` (plugin version, build info, `remoteEntry`, etc.), and any additional asset analysis. Ideal for debugging or merging stats across environments.
9+
- `mf-manifest.json`: a runtime-oriented manifest distilled from the stats. It keeps the stable structure that Module Federation consumers read when loading remote modules. The exposes/shared/remotes entries describe what is actually available to consumers.
710

811
The `PluginManifestOptions` types are as follows:
912

@@ -29,6 +32,8 @@ manifest filePath
2932

3033
manifest fileName
3134

35+
If `fileName` is provided, the companion stats file automatically receives a `-stats` suffix (for example, `fileName: 'mf.json'` produces both `mf.json` and `mf-stats.json`). Generated files are written under `filePath` when that option is set.
36+
3237
## disableAssetsAnalyze
3338

3439
:::warning

apps/website-new/docs/en/guide/troubleshooting/other.mdx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,14 @@ export default function MFLinkPlugin(): ModuleFederationRuntimePlugin {
120120
};
121121
}
122122
```
123+
124+
125+
## Multiple assets emit different content to the same filename mf-manifest.json
126+
127+
### Reason
128+
129+
In Rspack `1.6.0-beta.0`, we ported the manifest implementation to Rust. Upgrading Rspack without upgrading the MF-related packages will cause this error.
130+
131+
### Solution
132+
133+
Upgrade the `@module-federation` scoped npm package to version 0.21.0 or later.

apps/website-new/docs/zh/configure/manifest.mdx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
- 类型:`boolean | PluginManifestOptions`
44
- 默认值:`undefined`
55

6-
用于控制是否生成 manifest ,以及对应的生成配置。
6+
用于控制是否生成 manifest ,以及对应的生成配置。启用后插件会在每次构建中同时产出 `mf-manifest.json``mf-stats.json`(名称可通过 `fileName` 自定义),并写入到构建产物中,供其他工具在 `processAssets` 钩子或构建结果中直接读取。
7+
8+
- `mf-stats.json`:包含完整的构建统计信息,如 exposes/shared/remotes 的资源列表、`metaData`(插件版本、构建信息、`remoteEntry` 等)以及额外的资产分析结果,适合用于后续合并或诊断。
9+
- `mf-manifest.json`:在 stats 基础上提炼出的运行时清单,结构稳定,供 Module Federation 消费端在加载远程模块时读取。文件中的 exposes/shared/remotes 对应线上对外暴露的能力。
710

811
`PluginManifestOptions` 类型如下:
912

@@ -29,6 +32,8 @@ manifest 存放路径
2932

3033
manifest 文件名称
3134

35+
如果设置了 `fileName`,对应的 stats 文件名会自动附加 `-stats` 后缀(例如 `fileName: 'mf.json'` 时会同时生成 `mf.json``mf-stats.json`)。所有文件都会写入 `filePath`(若配置)指定的子目录。
36+
3237
## disableAssetsAnalyze
3338

3439
:::warning

apps/website-new/docs/zh/guide/troubleshooting/other.mdx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,13 @@ export default function MFLinkPlugin(): ModuleFederationRuntimePlugin {
9494
};
9595
}
9696
```
97+
98+
## Multiple assets emit different content to the same filename mf-manifest.json
99+
100+
### 原因
101+
102+
在 Rspack `1.6.0-beta.0` 中,我们将 manifest 实现移植到了 Rust 侧,如果升级了 Rspack 而没有升级 MF 相关的 package 则会造成此错误。
103+
104+
### 解决方案
105+
106+
升级 `@module-federation` scope 下的 npm 包至 `0.21.0` 及以上版本。

packages/enhanced/src/lib/container/ModuleFederationPlugin.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,6 @@ class ModuleFederationPlugin implements WebpackPluginInstance {
234234
this._statsPlugin.apply(compiler);
235235
}
236236
}
237-
238-
get statsResourceInfo() {
239-
return this._statsPlugin?.resourceInfo;
240-
}
241237
}
242238

243239
export default ModuleFederationPlugin;

packages/enhanced/src/wrapper/ModuleFederationPlugin.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,4 @@ export default class ModuleFederationPlugin implements WebpackPluginInstance {
111111
}).apply(compiler);
112112
}
113113
}
114-
115-
get statsResourceInfo(): Partial<ResourceInfo> | undefined {
116-
return this._mfPlugin?.statsResourceInfo;
117-
}
118114
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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 manifestPath = path.join(__dirname, 'mf-manifest.json');
6+
7+
const stats = JSON.parse(fs.readFileSync(statsPath, 'utf-8'));
8+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
9+
10+
it('should still emit the remote entry', () => {
11+
const remoteEntryFile = stats.metaData.remoteEntry.name;
12+
const remoteEntryPath = path.join(__dirname, remoteEntryFile);
13+
expect(fs.existsSync(remoteEntryPath)).toBe(true);
14+
});
15+
16+
it('should omit asset details from stats when disableAssetsAnalyze is true', () => {
17+
expect(stats.shared).toHaveLength(1);
18+
expect(stats.shared[0].assets.js.sync).toEqual([]);
19+
expect(stats.shared[0].assets.js.async).toEqual([]);
20+
expect(stats.exposes).toHaveLength(1);
21+
expect(stats.exposes[0].assets.js.sync).toEqual([]);
22+
expect(stats.exposes[0].assets.js.async).toEqual([]);
23+
});
24+
25+
it('should omit asset details from manifest when disableAssetsAnalyze is true', () => {
26+
expect(manifest.shared).toHaveLength(1);
27+
expect(manifest.shared[0].assets.js.sync).toEqual([]);
28+
expect(manifest.shared[0].assets.js.async).toEqual([]);
29+
expect(manifest.exposes).toHaveLength(1);
30+
expect(manifest.exposes[0].assets.js.sync).toEqual([]);
31+
expect(manifest.exposes[0].assets.js.async).toEqual([]);
32+
});
33+
34+
it('should mark remote usage locations as UNKNOWN', () => {
35+
expect(stats.remotes).toEqual(
36+
expect.arrayContaining([
37+
expect.objectContaining({
38+
usedIn: ['UNKNOWN'],
39+
}),
40+
]),
41+
);
42+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const lazy = true;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import react from 'react';
2+
import remote from 'remote';
3+
4+
global.react = react;
5+
global.remote = remote;
6+
7+
import('./lazy-module').then((r) => {
8+
console.log('lazy module: ', r);
9+
});
10+
11+
export const ok = true;

0 commit comments

Comments
 (0)