Webpack module fedoration
module fedoration 是 webpack 5 推出的一项全新功能。它能够为 webpack 提供远程模块
以下使用 mf 简称
使用
构建模块
指定远程入口文件 scope 以及要暴露的模块
// shell
new ModuleFederationPlugin({
name: "shell",
filename: "remoteEntry.js",
exposes: {
"./shell": "./src/Shell.tsx",
}
}),
声明模块(可选)
需要在 plugin 中声明所用的远程模块
// app
new ModuleFederationPlugin({
remotes: {
shell: "shell@https://cl-shell.vercel.app/remoteEntry.js"
}
}),
使用模块
一般会使用异步加载来消费模块
const Shell = React.lazy(() => import("shell/shell"));
import shell from "shell/shell";
原生不支持同步加载,需要社区 plugin 支持
https://github.com/webpack/webpack/issues/12258
在不使用 ModuleFederationPlugin 选择在运行时加载 mf 模块时,可以使用下面 API
// 加载 remoteEntry.js 之后
// scope -> name
// module -> expose
function loadComponent(scope: any, module: any) {
return async () => {
await __webpack_init_sharing__("default");
const container = window[scope];
await container.init(__webpack_share_scopes__.default);
const factory = await window[cpm].get(module);
const Module = factory();
return Module;
};
}
与微前端相比
mf 经常与微前端相提并论,但其实 微前端一般倾向于将 app 视为基础颗粒度,而 mf 则将更加细的模块视为基础颗粒度。与 诸如 qiankun 之类的微前端框架相比,mf
- 无 js 沙盒
- 无样式隔离
但是 mf 在 依赖共享 上有着传统微前端做不到的能力,传统微前端框架要想共享依赖,一般做法是使用 external + CDN,但是这会污染全局变量,一旦碰到像 Vue2 和 Vue3 共存的场景就无力解决。另外还需去保证消费方提供的相应的依赖。而 mf 则会默认为 shared 依赖在每个应用打包一份 fallback 依赖,尽管在使用的时候可能不会加载,但是能确保稳定。
new ModuleFederationPlugin({
shared: ['react', 'lodash']
}),
DX
跨项目的开发,远程模块对 TypeScript 的消费端极其不友好,传统微前端暴露给消费者的 API 较少,所以问题不大。但是 mf 则可能暴露比较多的 API,这时我们必须提供 d.ts 来提升开发体验,目前官方无相应方案,需要周边工具来弥补这一缺陷 @efox/emp-tune-dts-plugin