mf-integrate
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMF Scaffold — Add Module Federation to an Existing Project
MF脚手架——为现有项目添加Module Federation
Step 1: Detect project
步骤1:检测项目
Call the Skill (pass ) to collect MFContext.
mf-context$ARGUMENTSIf no bundler can be detected (no , , , , , found), this is likely a new project. Tell the user:
rsbuild.configrspack.configwebpack.configmodern.confignext.configvite.configThis looks like a new project. Run the following command to scaffold a full Module Federation project:bashnpm create module-federation@latest
Then stop.
If MF is already configured (MFContext shows existing or ), inform the user what is already configured and ask if they want to add/modify the configuration or stop.
remotesexposes调用 Skill(传入)以收集MFContext。
mf-context$ARGUMENTS如果未检测到任何打包工具(未找到、、、、、),则这很可能是一个新项目。请告知用户:
rsbuild.configrspack.configwebpack.configmodern.confignext.configvite.config这看起来是一个新项目。运行以下命令来搭建完整的Module Federation项目:bashnpm create module-federation@latest
然后终止流程。
如果已配置MF(MFContext显示存在或配置),则告知用户已有的配置内容,并询问是否需要添加/修改配置或终止操作。
remotesexposesStep 2: Gather parameters
步骤2:收集参数
Ask the user the following questions (combine into one AskUserQuestion call):
-
Role — What role should this app play?
- — loads modules from remote apps (default)
consumer - — exposes modules to other apps
provider - — exposes modules and loads remote modules
both
-
App name — What should the MF name be for this app?
- Suggest the field from
name(snake_case, no hyphens). Hyphens are not allowed in MF names.package.json
- Suggest the
-
Role-specific:
- If consumer or both: Do you want to connect to the public demo provider to see MF working immediately, or configure your own remotes?
- — use the public demo provider (default for consumers)
demo - — I'll specify my own remote URLs
custom
- If provider or both: What module(s) do you want to expose? Provide pairs, e.g.
key: path. If unsure, use./Button: ./src/components/Button.tsxas a default.'.' : './src/index'
- If consumer or both: Do you want to connect to the public demo provider to see MF working immediately, or configure your own remotes?
向用户询问以下问题(合并为一次询问):
-
角色——此应用应扮演什么角色?
- ——从远程应用加载模块(默认值)
consumer - ——向其他应用暴露模块
provider - ——同时暴露模块并加载远程模块
both
-
应用名称——此应用的MF名称是什么?
- 建议使用中的
package.json字段(采用蛇形命名,无连字符)。MF名称不允许包含连字符。name
- 建议使用
-
角色专属参数:
- 如果是消费者或两者兼具:是否要连接到公开的演示提供者以立即查看MF运行效果,还是配置自定义远程应用?
- ——使用公开演示提供者(消费者默认选项)
demo - ——我将指定自己的远程URL
custom
- 如果是提供者或两者兼具:要暴露哪些模块?请提供格式的配置,例如
key: path。若不确定,可使用默认配置./Button: ./src/components/Button.tsx。'.' : './src/index'
- 如果是消费者或两者兼具:是否要连接到公开的演示提供者以立即查看MF运行效果,还是配置自定义远程应用?
Step 3: Build the MF config object
步骤3:构建MF配置对象
Construct the MF config based on the gathered parameters:
根据收集到的参数构建MF配置:
Remote entries (for consumer / both)
远程入口(消费者/两者兼具)
Demo provider (use when user chose ):
demots
remotes: {
'provider': 'rslib_provider@https://unpkg.com/module-federation-rslib-provider@latest/dist/mf/mf-manifest.json',
},The demo provider exposes a React component at . The user can import it in their app:
'provider'tsx
import ProviderApp from 'provider';Custom remotes (use when user chose ):
Ask the user to provide remote entries in the format , then use them as-is.
customname: url演示提供者(当用户选择时使用):
demots
remotes: {
'provider': 'rslib_provider@https://unpkg.com/module-federation-rslib-provider@latest/dist/mf/mf-manifest.json',
},该演示提供者暴露了一个React组件,用户可在应用中通过以下方式导入:
tsx
import ProviderApp from 'provider';自定义远程应用(当用户选择时使用):
请用户提供格式的远程入口,直接使用用户提供的配置。
customname: urlExposes (for provider / both)
暴露模块(提供者/两者兼具)
Use the entries provided by the user. Example:
ts
exposes: {
'./Button': './src/components/Button.tsx',
},使用用户提供的配置项。示例:
ts
exposes: {
'./Button': './src/components/Button.tsx',
},Shared deps
共享依赖
Read to check which frameworks are present. Set singletons accordingly:
package.json- If +
reactpresent: add both asreact-dom{ singleton: true } - If present: add as
vue{ singleton: true } - If both (rare): add all as singletons
读取以检查当前项目使用的框架,并相应地设置单例模式:
package.json- 如果存在+
react:将两者设置为react-dom{ singleton: true } - 如果存在:将其设置为
vue{ singleton: true } - 如果两者都存在(罕见情况):将所有框架都设置为单例
Step 4: Generate files
步骤4:生成文件
Apply the correct pattern for the detected bundler:
根据检测到的打包工具应用对应的配置模式:
Rsbuild
Rsbuild
Detected by: / in project root.
rsbuild.config.tsrsbuild.config.js检测依据:项目根目录下存在 / 。
rsbuild.config.tsrsbuild.config.js4a. Create module-federation.config.ts
module-federation.config.ts4a. 创建module-federation.config.ts
module-federation.config.tsts
import { createModuleFederationConfig } from '@module-federation/rsbuild-plugin';
export default createModuleFederationConfig({
name: '<app-name>',
// exposes: { ... }, // provider / both only
// remotes: { ... }, // consumer / both only
shareStrategy: 'loaded-first',
shared: {
// react + react-dom or vue — from Step 3
},
});ts
import { createModuleFederationConfig } from '@module-federation/rsbuild-plugin';
export default createModuleFederationConfig({
name: '<app-name>',
// exposes: { ... }, // 仅提供者/两者兼具时需要
// remotes: { ... }, // 仅消费者/两者兼具时需要
shareStrategy: 'loaded-first',
shared: {
// react + react-dom 或 vue —— 来自步骤3
},
});4b. Modify rsbuild.config.ts
rsbuild.config.ts4b. 修改rsbuild.config.ts
rsbuild.config.tsAdd to the plugins array:
pluginModuleFederationdiff
+import { pluginModuleFederation } from '@module-federation/rsbuild-plugin';
+import moduleFederationConfig from './module-federation.config';
export default defineConfig({
plugins: [
pluginReact(),
+ pluginModuleFederation(moduleFederationConfig),
],
});在插件数组中添加:
pluginModuleFederationdiff
+import { pluginModuleFederation } from '@module-federation/rsbuild-plugin';
+import moduleFederationConfig from './module-federation.config';
export default defineConfig({
plugins: [
pluginReact(),
+ pluginModuleFederation(moduleFederationConfig),
],
});4c. Install
4c. 安装依赖
bash
pnpm add @module-federation/rsbuild-pluginbash
pnpm add @module-federation/rsbuild-pluginModern.js
Modern.js
Detected by: / in project root.
modern.config.tsmodern.config.js检测依据:项目根目录下存在 / 。
modern.config.tsmodern.config.js4a. Create module-federation.config.ts
module-federation.config.ts4a. 创建module-federation.config.ts
module-federation.config.tsts
import { createModuleFederationConfig } from '@module-federation/modern-js-v3';
export default createModuleFederationConfig({
name: '<app-name>',
// exposes: { ... }, // provider / both only
// remotes: { ... }, // consumer / both only
shared: {
// react + react-dom or vue — from Step 3
},
});ts
import { createModuleFederationConfig } from '@module-federation/modern-js-v3';
export default createModuleFederationConfig({
name: '<app-name>',
// exposes: { ... }, // 仅提供者/两者兼具时需要
// remotes: { ... }, // 仅消费者/两者兼具时需要
shared: {
// react + react-dom 或 vue —— 来自步骤3
},
});4b. Modify modern.config.ts
modern.config.ts4b. 修改modern.config.ts
modern.config.tsdiff
+import { moduleFederationPlugin } from '@module-federation/modern-js-v3';
export default defineConfig({
plugins: [
appTools(),
+ moduleFederationPlugin(),
],
});diff
+import { moduleFederationPlugin } from '@module-federation/modern-js-v3';
export default defineConfig({
plugins: [
appTools(),
+ moduleFederationPlugin(),
],
});4c. For consumer: add type paths
4c. 消费者:添加类型路径
Modify to resolve remote types:
tsconfig.jsondiff
{
"compilerOptions": {
+ "paths": {
+ "*": ["./@mf-types/*"]
+ }
}
}修改以解析远程类型:
tsconfig.jsondiff
{
"compilerOptions": {
+ "paths": {
+ "*": ["./@mf-types/*"]
+ }
}
}4d. Install
4d. 安装依赖
bash
pnpm add @module-federation/modern-js-v3bash
pnpm add @module-federation/modern-js-v3Rspack
Rspack
Detected by: / in project root.
rspack.config.tsrspack.config.js检测依据:项目根目录下存在 / 。
rspack.config.tsrspack.config.js4a. Modify rspack.config.ts
/ rspack.config.js
rspack.config.tsrspack.config.js4a. 修改rspack.config.ts
/ rspack.config.js
rspack.config.tsrspack.config.jsAdd and :
ModuleFederationPluginexperiments.asyncStartupdiff
+const { ModuleFederationPlugin } = require('@module-federation/enhanced/rspack');
module.exports = {
+ experiments: {
+ asyncStartup: true,
+ },
plugins: [
+ new ModuleFederationPlugin({
+ name: '<app-name>',
+ // exposes: { ... }, // provider / both only
+ // remotes: { ... }, // consumer / both only
+ shared: {
+ // from Step 3
+ },
+ }),
],
};Note:requires Rspack > 1.7.4.experiments.asyncStartup
添加和:
ModuleFederationPluginexperiments.asyncStartupdiff
+const { ModuleFederationPlugin } = require('@module-federation/enhanced/rspack');
module.exports = {
+ experiments: {
+ asyncStartup: true,
+ },
plugins: [
+ new ModuleFederationPlugin({
+ name: '<app-name>',
+ // exposes: { ... }, // 仅提供者/两者兼具时需要
+ // remotes: { ... }, // 仅消费者/两者兼具时需要
+ shared: {
+ // 来自步骤3
+ },
+ }),
],
};注意:需要Rspack版本 > 1.7.4。experiments.asyncStartup
4b. Install
4b. 安装依赖
bash
pnpm add @module-federation/enhancedbash
pnpm add @module-federation/enhancedWebpack
Webpack
Detected by: / in project root.
webpack.config.tswebpack.config.js检测依据:项目根目录下存在 / 。
webpack.config.tswebpack.config.js4a. Modify webpack.config.js
webpack.config.js4a. 修改webpack.config.js
webpack.config.jsdiff
+const { ModuleFederationPlugin } = require('@module-federation/enhanced/webpack');
module.exports = {
+ experiments: {
+ asyncStartup: true,
+ },
plugins: [
+ new ModuleFederationPlugin({
+ name: '<app-name>',
+ filename: 'remoteEntry.js',
+ // exposes: { ... }, // provider / both only
+ // remotes: { ... }, // consumer / both only
+ shared: {
+ // from Step 3
+ },
+ }),
],
};diff
+const { ModuleFederationPlugin } = require('@module-federation/enhanced/webpack');
module.exports = {
+ experiments: {
+ asyncStartup: true,
+ },
plugins: [
+ new ModuleFederationPlugin({
+ name: '<app-name>',
+ filename: 'remoteEntry.js',
+ // exposes: { ... }, // 仅提供者/两者兼具时需要
+ // remotes: { ... }, // 仅消费者/两者兼具时需要
+ shared: {
+ // 来自步骤3
+ },
+ }),
],
};4b. Install
4b. 安装依赖
bash
pnpm add @module-federation/enhancedbash
pnpm add @module-federation/enhancedNext.js
Next.js
Detected by: / / in project root.
next.config.tsnext.config.mjsnext.config.jsDeprecation warning:only supports Pages Router (not App Router) and is no longer actively maintained. For new projects, consider using Rsbuild or Modern.js instead.@module-federation/nextjs-mf
检测依据:项目根目录下存在 / / 。
next.config.tsnext.config.mjsnext.config.js弃用警告:仅支持Pages Router(不支持App Router),且不再积极维护。对于新项目,建议使用Rsbuild或Modern.js。@module-federation/nextjs-mf
4a. Modify next.config.mjs
next.config.mjs4a. 修改next.config.mjs
next.config.mjsdiff
+import { NextFederationPlugin } from '@module-federation/nextjs-mf';
const nextConfig = {
webpack(config, options) {
+ config.plugins.push(
+ new NextFederationPlugin({
+ name: '<app-name>',
+ filename: 'static/chunks/remoteEntry.js',
+ // exposes: { ... }, // provider / both only
+ // remotes: { // consumer / both only
+ // remote: `remote@http://localhost:3001/static/${options.isServer ? 'ssr' : 'chunks'}/remoteEntry.js`,
+ // },
+ shared: {},
+ extraOptions: {
+ exposePages: true,
+ enableImageLoaderFix: true,
+ enableUrlLoaderFix: true,
+ },
+ })
+ );
return config;
},
};diff
+import { NextFederationPlugin } from '@module-federation/nextjs-mf';
const nextConfig = {
webpack(config, options) {
+ config.plugins.push(
+ new NextFederationPlugin({
+ name: '<app-name>',
+ filename: 'static/chunks/remoteEntry.js',
+ // exposes: { ... }, // 仅提供者/两者兼具时需要
+ // remotes: { // 仅消费者/两者兼具时需要
+ // remote: `remote@http://localhost:3001/static/${options.isServer ? 'ssr' : 'chunks'}/remoteEntry.js`,
+ // },
+ shared: {},
+ extraOptions: {
+ exposePages: true,
+ enableImageLoaderFix: true,
+ enableUrlLoaderFix: true,
+ },
+ })
+ );
return config;
},
};4b. Enable local Webpack
4b. 启用本地Webpack
Add to :
.env.localNEXT_PRIVATE_LOCAL_WEBPACK=true在中添加:
.env.localNEXT_PRIVATE_LOCAL_WEBPACK=true4c. Install
4c. 安装依赖
bash
pnpm add @module-federation/nextjs-mf webpack -Dbash
pnpm add @module-federation/nextjs-mf webpack -DVite
Vite
Detected by: / in project root.
vite.config.tsvite.config.js检测依据:项目根目录下存在 / 。
vite.config.tsvite.config.js4a. Modify vite.config.ts
vite.config.ts4a. 修改vite.config.ts
vite.config.tsdiff
+import { federation } from '@module-federation/vite';
export default defineConfig({
plugins: [
+ federation({
+ name: '<app-name>',
+ // exposes: { ... }, // provider / both only
+ // remotes: { ... }, // consumer / both only
+ shared: {
+ // from Step 3
+ },
+ }),
],
});diff
+import { federation } from '@module-federation/vite';
export default defineConfig({
plugins: [
+ federation({
+ name: '<app-name>',
+ // exposes: { ... }, // 仅提供者/两者兼具时需要
+ // remotes: { ... }, // 仅消费者/两者兼具时需要
+ shared: {
+ // 来自步骤3
+ },
+ }),
],
});4b. Install
4b. 安装依赖
bash
pnpm add @module-federation/vitebash
pnpm add @module-federation/viteStep 5: Auto-insert remote component (consumer / both only)
步骤5:自动插入远程组件(仅消费者/两者兼具)
Skip this step entirely for provider-only role.
Ask the user:
Do you want me to automatically add the remote component to your app's entry so you can see it working right away?
If the user says no, just show the code snippet as a reference and move on to Step 6.
If the user says yes:
纯提供者角色跳过此步骤。
询问用户:
是否需要我自动将远程组件添加至应用入口,以便您立即查看运行效果?
如果用户选择否,则仅展示代码片段作为参考,然后进入步骤6。
如果用户选择是:
5a. Locate the entry file
5a. 定位入口文件
Search for the entry component file in this priority order:
| Bundler | Candidates (in order) |
|---|---|
| Rsbuild | |
| Modern.js | |
| Webpack / Rspack | |
| Next.js | |
| Vite | |
Read the first file that exists. If none found, tell the user which file to modify manually and show the snippet — do not attempt blind writes.
按以下优先级搜索入口组件文件:
| 打包工具 | 候选文件(优先级顺序) |
|---|---|
| Rsbuild | |
| Modern.js | |
| Webpack / Rspack | |
| Next.js | |
| Vite | |
读取第一个存在的文件。如果未找到任何文件,告知用户需要手动修改的文件并展示代码片段——请勿尝试盲目写入。
5b. Determine remote name and import path
5b. 确定远程名称和导入路径
Use the remote name from the config generated in Step 4:
- If demo provider: remote name is , import path is
provider'provider' - If custom remotes: use the first remote name the user specified
使用步骤4中生成的配置里的远程名称:
- 如果是演示提供者:远程名称为,导入路径为
provider'provider' - 如果是自定义远程应用:使用用户指定的第一个远程名称
5c. Edit the entry file
5c. 编辑入口文件
Add the import at the top of the file (after existing imports) and render the component inside the existing JSX return.
For React (Rsbuild / Rspack / Webpack / Vite)
Add import after the last existing import line:
tsx
import ProviderApp from 'provider';Insert inside the existing JSX return. Find a natural place — inside a , after existing content. Do not restructure the component; just append the element.
<ProviderApp /><div>For Modern.js ()
src/routes/page.tsxSame pattern — add import and render in the returned JSX.
<ProviderApp />For Next.js ()
pages/index.tsxSame pattern — add import and render in the returned JSX.
<ProviderApp />在文件顶部(现有导入之后)添加导入语句,并在现有JSX的返回值中渲染该组件。
React项目(Rsbuild / Rspack / Webpack / Vite)
在最后一条导入语句后添加:
tsx
import ProviderApp from 'provider';在现有JSX返回值中插入。选择合适的位置——例如在某个内,现有内容之后。请勿重构组件,仅追加元素。
<ProviderApp /><div>Modern.js()
src/routes/page.tsx采用相同模式——添加导入语句并在返回的JSX中渲染。
<ProviderApp />Next.js()
pages/index.tsx采用相同模式——添加导入语句并在返回的JSX中渲染。
<ProviderApp />5d. Add TypeScript declaration (if TypeScript project)
5d. 添加TypeScript声明(TypeScript项目)
Check if exists. If it does, create (or add to an existing / if present):
tsconfig.jsonsrc/remote.d.tssrc/declarations.d.tssrc/env.d.tsts
declare module '<remote-name>' {
const Component: React.ComponentType;
export default Component;
}Replace with the actual remote name (e.g., ).
<remote-name>provider检查是否存在。如果存在,创建(或添加至已有的 / ):
tsconfig.jsonsrc/remote.d.tssrc/declarations.d.tssrc/env.d.tsts
declare module '<remote-name>' {
const Component: React.ComponentType;
export default Component;
}将替换为实际的远程名称(例如)。
<remote-name>providerProvider: how to verify the exposed module
提供者:如何验证暴露的模块
Tell the user that after running the dev server, the manifest will be available at:
- Rsbuild / Rspack / Webpack / Modern.js:
http://localhost:<port>/mf-manifest.json - Next.js:
http://localhost:<port>/static/chunks/remoteEntry.js
Another app can reference this app as a remote using:
ts
remotes: {
'<app-name>': '<app-name>@http://localhost:<port>/mf-manifest.json',
},告知用户启动开发服务器后,清单文件将在以下地址可用:
- Rsbuild / Rspack / Webpack / Modern.js:
http://localhost:<port>/mf-manifest.json - Next.js:
http://localhost:<port>/static/chunks/remoteEntry.js
其他应用可通过以下配置将此应用作为远程应用引用:
ts
remotes: {
'<app-name>': '<app-name>@http://localhost:<port>/mf-manifest.json',
},Step 6: Summary
步骤6:总结
Output a concise summary:
- What files were created or modified
- What packages were installed
- How to start the dev server (use existing script from )
package.json - Next steps (e.g., add more remotes, configure shared deps, set up type generation)
输出简洁的总结内容:
- 创建或修改了哪些文件
- 安装了哪些依赖包
- 如何启动开发服务器(使用中的现有脚本)
package.json - 后续步骤(例如添加更多远程应用、配置共享依赖、设置类型生成)