介绍
Webpack 5 中引入的模块联合提供了用于构建微前端架构的运行时集成机制。与构建时集成方法不同,它使独立部署的应用程序能够在运行时共享代码,从而促进团队自治和增量迁移,而无需协调发布。
从本质上讲,模块联合允许 JavaScript 应用程序在运行时从另一个应用程序动态加载代码。每个参与的应用程序都会公开一个 remoteEntry.js 文件作为入口点。当主机应用程序需要来自远程的组件时,它会在运行时获取 remoteEntry.js 并按需解析所需的模块。
使用 ModuleFederationPlugin 进行配置
ModuleFederationPlugin 是用于定义应用程序如何共享代码的主要配置界面。
const { ModuleFederationPlugin } = require("webpack").container;
new ModuleFederationPlugin({
name: "shell",
remotes: {
catalog: "catalog@https://cdn.example.com/catalog/remoteEntry.js",
},
exposes: {
"./Header": "./src/components/Header",
},
shared: {
react: { singleton: true, requiredVersion: "^18.0.0" },
},
});
name 字段用作应用程序的唯一标识符。 exposes 映射声明哪些模块可供其他应用程序使用,而 remotes 指定使用的外部应用程序。 shared 配置确保像 React 这样的关键库仅加载一次,从而防止浏览器中出现重复实例。
RemoteEntry.js 运行时
当浏览器加载主机应用程序时,它不会立即获取联合模块。相反,主机的 webpack 运行时会初始化共享范围,并且仅当需要远程模块时,才会获取相应的 remoteEntry.js。该脚本包含可用模块及其块位置的清单。
运行时依赖 __webpack_init_sharing__ 来初始化共享范围,并依靠 __webpack_share_scopes__ 来管理跨联合边界的共享模块的解析。了解此网络瀑布对于调试生产中的负载性能至关重要。
共享依赖策略
管理共享依赖关系是模块联合最关键的方面。 shared 配置支持多种模式:
| 模式 | 描述 | 使用案例 |
|---|---|---|
| 单例 | 全球只有一个实例 | React、Vue、Angular |
| 版本范围 | Semver 兼容性检查 | 具有严格 API 的库 |
| 渴望 | 预先加载,不偷懒 | 关键共享实用程序 |
| 后备 | 用于版本不匹配 | 优雅降级 |
对于 React 应用程序,单例模式是强制性的——同一 DOM 中的两个 React 实例会导致不可预测的行为。将 singleton: true 与 requiredVersion: '^18.0.0' 结合起来,以确保所有联合模块都使用兼容的 React 实例。
错误处理和回退
远程模块可能会因网络问题、部署错误或版本不匹配而失败。强大的架构可以优雅地处理这些故障。
const FederatedButton = React.lazy(() =>
import("catalog/Button").catch(() => import("./fallback/Button"))
);
function App() {
return (
<ErrorBoundary fallback={<FallbackUI />}>
<Suspense fallback={<Skeleton />}>
<FederatedButton />
</Suspense>
</ErrorBoundary>
);
}
使用 Suspense 进行加载状态的分层错误处理、渲染失败的错误边界以及本地回退模块可确保远程故障不会破坏整个应用程序。
部署模式
模块联合可以实现灵活的部署。共置部署独立构建每个微前端,但将它们部署在一起。单独的部署为每个团队提供了完全的自主权,遥控器指向实时 URL。版本化部署使用标记引用来保证稳定性。
典型的 CI/CD 管道独立构建每个微前端,将工件发布到 CDN,并更新主机引用。缓存失效至关重要——每个部署都应该生成唯一的块哈希值,以防止过时的缓存服务于过时的模块。
结论
Module Federation 提供了一种经过生产验证的微前端架构方法。从单一主机和远程设置开始,尽早投资共享依赖项管理,并实施强大的错误处理。使用 webpack-bundle-analyzer 监视包大小,并使用浏览器开发工具跟踪运行时分辨率。官方 Module Federation 文档和 Zack Jackson 的示例存储库提供了很好的起点。

