Bridge 概览
介绍
Bridge
是 Module Federation
提供的工具函数,用于加载应用级别模块。
所谓 “应用级别模块”,即 能像应用一样运行的模块,具备应用的框架渲染能力及路由能力。
通过 Bridge
你可以在不同框架中渲染你的应用,并能保证应用间路由能协同工作。这对于微前端应用将非常有帮助。
工具包
@module-federation/bridge-react
@module-federation/bridge-react
适用于 React 框架类型,目前我们支持 React v16、v17、v18 版本。
在此工具包中我们提供 两个 API:
用于创建 React 应用类型模块导出,如果你的应用是 React 类型 且希望作为应用类型模块被另一个 MF 应用加载,那么你应该使用它为你的应用创造符合规范的导出。
用于在 React 应用中加载应用类型模块,所加载的模块必须被 createBridgeComponent
所包裹,createRemoteComponent
将自动在你的应用中创建渲染上下文以保证模块能正常工作。
@module-federation/bridge-react
的使用见 Host demo、Remote demo。
@module-federation/bridge-vue3
@module-federation/bridge-vue3
适用于 Vue 框架类型,目前我们支持 Vue v3 版本。
在此工具包中我们提供 两个 API:
用于创建 Vue 应用类型模块导出,如果你的应用是 Vue v3 类型 且希望作为应用类型模块被另一个 MF 应用加载,那么你应该使用它为你的应用创造符合规范的导出。
用于在 Vue 应用中加载应用类型模块,所加载的模块必须被 createBridgeComponent
所包裹,createRemoteComponent
将自动在你的应用中创建渲染上下文以保证模块能正常工作。
FAQ
Why Bridge?
Bridge 主要用于解决两个问题:
- 跨应用框架(React、Vue)加载和渲染
- 支持加载带路由的模块(路由可以很好的协同工作)
这两个问题都是「微前端框架」里重要的特性
未提供对应框架的 bridge 如何解决?
目前 Module Federation
提供了官方的 bridge 工具包,如果你需要其他框架的 bridge 工具包,可以通过 issue 给我们提供反馈,也可以参考现有的 Bridge
如何实现.
Bridge
的实现非常简单,核心就是基于 DOM
渲染,下面是伪代码:
导出模块
export default function () {
const rootMap = new Map<any, ReactDOM.Root>();
return {
render(info: { dom: HTMLElement; basename?: string; memoryRoute?: { entryPath: string; } }) {
const root = ReactDOM.createRoot(info.dom);
rootMap.set(info.dom, root);
root.render(
<App />,
);
},
destroy(info: { dom: HTMLElement }) {
const root = rootMap.get(info.dom);
root?.unmount();
},
}
}
加载模块
const LazyComponent = React.lazy(async () => {
const m = await loadRemote('remote1/export-app');
const providerInfo = m.default;
return {
default: () => {
const rootRef = useRef(null);
const providerInfoRef = useRef<any>(null);
useEffect(() => {
const providerReturn = providerInfo();
providerInfoRef.current = providerReturn;
providerReturn.render(renderProps);
return () => {
providerInfoRef.current?.destroy({
dom: renderDom.current,
});
};
}, []);
return <div ref={rootRef}></div>;
}
};
});
function Component () {
return (<React.Suspense fallback={<div>loading</div>}>
<LazyComponent />
</React.Suspense>)
}