#Runtime 接入
目前 Module Federation 提供了两种注册模块和加载模块的方式:
-
一种是在构建插件中声明(一般是在
module-federation.config.ts文件中声明)。 -
另一种方式是直接通过
runtime的 api 进行模块注册和加载。
两种模式并不冲突可结合使用。你可以根据你的实际场景灵活选取模块注册方式和时机。
#注册方式差异
| 运行时注册模块 | 插件中注册模块 |
|---|---|
可脱离构建插件使用,在 webpack4 等项目中可直接使用纯运行时进行模块注册和加载 | 构建插件需要是 webpack5 或以上 |
| 支持动态注册模块 | 不支持动态注册模块 |
不支持 import 语法加载模块 | 支持 import 同步语法加载模块 |
支持 loadRemote 加载模块 | 支持 loadRemote 加载模块 |
设置 shared 必须提供具体版本和实例信息 | 设置 shared 只需要配置规则即可,无须提供具体版本及实例信息 |
shared 依赖只能供外部使用,无法使用外部 shared 依赖 | shared 依赖按照特定规则双向共享 |
可以通过 runtime 的 plugin 机制影响加载流程 | 目前不支持提供 plugin 影响加载流程 |
| 不支持远程类型提示 | 支持远程类型提示 |
若使用构建插件,项目启动时将自动创建 ModuleFederation 实例并存储于内存中。此时可直接调用 API,API 会自动从内存中获取构建运行时创建的 ModuleFederation 实例。
import { loadRemote } from '@module-federation/enhanced/runtime';
loadRemote('remote1');若未使用构建插件,则需手动创建 ModuleFederation 实例,之后调用相应 API。
import { createInstance } from '@module-federation/enhanced/runtime';
const mf = createInstance({
name: 'host',
remotes: [
{
name: 'remote1',
entry: 'http://localhost:2001/vmok-manifest.json',
},
],
});
mf.loadRemote('remote1');ModuleFederation 实例
ModuleFederation 类创建的对象,包含了运行时的所有功能。你可以在控制台输入 __FEDERATION__.__INSTANCES__ 来查看完整示例信息。
#安装
不同项目需要安装不同的 Runtime 包,并直接从这些包中引用 Runtime API。
- 大多数项目默认安装
@module-federation/enhanced - Modern.js 项目安装
@module-federation/modern-js-v3插件
#@module-federation/enhanced
npm
yarn
pnpm
bun
npm install @module-federation/enhanced --saveyarn add @module-federation/enhanced --savepnpm add @module-federation/enhanced --savebun add @module-federation/enhanced --saveimport { createInstance, loadRemote } from '@module-federation/enhanced/runtime';#Modern.js
npm
yarn
pnpm
bun
npm install @module-federation/modern-js-v3 --saveyarn add @module-federation/modern-js-v3 --savepnpm add @module-federation/modern-js-v3 --savebun add @module-federation/modern-js-v3 --saveimport { createInstance, loadRemote } from '@module-federation/modern-js-v3/runtime';Note
如果是 Modern.js v2 项目,请安装 @module-federation/modern-js,并从 @module-federation/modern-js/runtime 引用 Runtime API。
#模块注册
Build Plugin(使用构建插件)
Pure Runtime(未使用构建插件)
// 如果使用了构建插件,那么可以直接使用 `registerRemotes` 注册模块。
import { registerRemotes } from '@module-federation/enhanced/runtime';
registerRemotes([
{
name: 'remote1',
alias: 'remote-1',
entry: 'http://localhost:3001/mf-manifest.json',
}
]);// 如果没有使用构建插件,那么可以创建新的实例,并注册模块
import { createInstance } from '@module-federation/enhanced/runtime';
const mf = createInstance({
name: 'mf_host',
remotes: [
{
name: 'remote1',
alias: 'remote-1',
entry: 'http://localhost:3001/mf-manifest.json',
}
]
});
mf.registerRemotes([
{
name: 'remote1',
alias: 'remote-1',
entry: 'http://localhost:3001/mf-manifest.json',
}
]);#模块加载
Build Plugin(使用构建插件)
Pure Runtime(未使用构建插件)
// 如果使用了构建插件,那么可以直接使用 `loadRemote` 加载模块。
import { loadRemote } from '@module-federation/enhanced/runtime';
import React from 'react';
export default () => {
const MyButton = React.lazy(() =>
loadRemote('remote1').then(({ MyButton }) => {
return {
default: MyButton
};
}),
);
return (
<React.Suspense fallback="Loading Button">
<MyButton />
</React.Suspense>
);
}// 如果没有使用构建插件,那么可以创建新的实例,并注册模块
import { createInstance } from '@module-federation/enhanced/runtime';
import React from 'react';
const mf = createInstance({
name: 'mf_host',
remotes: [
{
name: 'remote1',
alias: 'remote-1',
entry: 'http://localhost:3001/mf-manifest.json',
}
]
});
export default () => {
const MyButton = React.lazy(() =>
mf.loadRemote('remote1').then(({ MyButton }) => {
return {
default: MyButton
};
}),
);
return (
<React.Suspense fallback="Loading Button">
<MyButton />
</React.Suspense>
);
}#加载匿名模块
Build Plugin(使用构建插件)
Pure Runtime(未使用构建插件)
// 如果使用了构建插件,那么可以直接使用 `loadRemote` 加载模块。
import React from 'react';
import { loadRemote } from '@module-federation/enhanced/runtime';
const RemoteButton = React.lazy(() => loadRemote('provider/button'));
// 也可通过模块别名加载:
// const RemoteButton = React.lazy(() => loadRemote('remotes-1/button'));
export default () => {
return (
<React.Suspense fallback="Loading Button">
<RemoteButton />
</React.Suspense>
);
}// 如果没有使用构建插件,那么可以创建新的实例,并注册模块
import { createInstance } from '@module-federation/enhanced/runtime';
import React from 'react';
// 创建实例
const mf = createInstance({
name: 'mf_host',
remotes: [
{
name: 'remote1',
alias: 'remote-1',
entry: 'http://localhost:3001/mf-manifest.json',
}
]
});
// 使用 实例 loadRemote API 加载模块
const RemoteButton = React.lazy(() => mf.loadRemote('provider/button'));
// 也可通过模块别名加载:
// const RemoteButton = React.lazy(() => mf.loadRemote('remotes-1/button'));
export default () => {
return (
<React.Suspense fallback="Loading Button">
<RemoteButton />
</React.Suspense>
);
}#加载具名模块
Build Plugin(使用构建插件)
Pure Runtime(未使用构建插件)
// 如果使用了构建插件,那么可以直接使用 `loadRemote` 加载模块。
import React from 'react';
import { loadRemote } from '@module-federation/enhanced/runtime';
export default () => {
const RemoteButton = React.lazy(() =>
loadRemote('remote1/button').then(({ RemoteButton }) => {
return {
default: RemoteButton
};
}),
);
return (
<React.Suspense fallback="Loading Button">
<RemoteButton />
</React.Suspense>
);
}// 如果没有使用构建插件,那么可以创建新的实例,并注册模块
import { createInstance } from '@module-federation/enhanced/runtime';
import React from 'react';
// 创建实例
const mf = createInstance({
name: 'mf_host',
remotes: [
{
name: 'remote1',
alias: 'remote-1',
entry: 'http://localhost:3001/mf-manifest.json',
}
]
});
export default () => {
const RemoteButton = React.lazy(() =>
// 使用 实例 loadRemote API 加载模块
mf.loadRemote('remote1/button').then(({ RemoteButton }) => {
return {
default: RemoteButton
};
}),
);
return (
<React.Suspense fallback="Loading Button">
<RemoteButton />
</React.Suspense>
);
}#加载工具函数
Build Plugin(使用构建插件)
Pure Runtime(未使用构建插件)
// 如果使用了构建插件,那么可以直接使用 `loadRemote` 加载模块。
import React from 'react';
import { loadRemote } from '@module-federation/enhanced/runtime';
// 加载 remote1 expose 的 util
loadRemote<{ add: (...args: Array<number>) => number }>('remote1/util').then((md) => {
md.add(1, 2);
});// 如果没有使用构建插件,那么可以创建新的实例,并注册模块
import { createInstance, loadRemote } from '@module-federation/enhanced/runtime';
import React from 'react';
// 创建实例
const mf = createInstance({
name: 'mf_host',
remotes: [
{
name: 'remote1',
alias: 'remote-1',
entry: 'http://localhost:3001/mf-manifest.json',
}
]
});
mf.loadRemote<{ add: (...args: Array<number>) => number }>('remote1/util').then((md) => {
md.add(1, 2);
});#继续阅读
- Runtime API:查看
createInstance、loadRemote、registerRemotes等 API。 - Runtime 插件:了解如何扩展运行时加载流程。
- Runtime Hooks:查看插件可使用的生命周期。