Module Federation(模块联邦)是 Webpack 5 中最令人激动的功能之一,被认为是 JavaScript 架构的变革者。它支持在 JavaScript 应用程序之间更独立、更简单地共享代码,使应用程序更具适应性和动态性。
本文将介绍什么是 Webpack 模块联邦,它是如何被使用和为什么使用它,以及通过使用它可以获得的好处。
什么是模块联邦?
Webpack 模块联邦使不同代码库之间的代码和依赖共享更加容易。该架构在运行时动态加载代码,减少了代码重复的频率,只有在需要时主应用程序才会下载缺失的依赖。
运行时共享
如上图,作为 Home
页面的Header
组件作为生产者发布,Detail
页面在运行时可以通过模块联邦消费 Header
组件,从而实现组件动态共享。
构建时共享
如上图,构建时共享是 Home
页面和 Detail
页面都会静态导入Header
组件。
模块联邦由 Webpack 维护者 Zack Jackson 发明,于 2020 年成为 Webpack 5 的旗舰功能。它不是一个框架,而是一个插件,提供了在构建项目时的灵活性。尽管模块联邦最初是用于异步加载 JavaScript 捆绑包,但后来还扩展到了帮助处理服务器端渲染。
Module Federation 的起源项目为 webpack-external-import,现已经并入 Webpack5, v2.2.4 为最后独立发布的版本。
模块联邦的重要性
Webpack 模块联邦是一个强大的功能,它正在改变 JavaScript 架构和微前端方法。如果正确使用,它可以为你的应用程序系统提供许多好处。
在引入模块联邦之前,代码共享往往不是一个平滑的过程。微前端的实施也变得更加复杂。
模块联邦是一种解决这些问题的架构,它革新了微前端策略。使用模块联邦,应用程序在运行时可以从另一个捆绑包或构建中动态运行代码,并具有共享代码和功能消费能力,为成功利用微前端技术铺平了道路。此外,使用可共享的依赖项提高了应用程序的紧凑性。模块联邦还让开发人员感到熟悉,因为它是 Webpack 生态系统的一部分,开发人员可能已经使用过。
所有这些标准使得 Webpack 模块联邦成为一个强大且重要的功能,你在未来的项目中应该考虑使用它。
模块联邦术语
在使用 Webpack 模块联邦时,你可能需要熟悉以下一些重要术语:
- 主机(Host):页面构建过程中首先初始化的 Webpack 构建称为主机。主机应用程序包含来自单页应用程序(SPA)或服务器端渲染(SSR)应用程序的典型功能,它引导并呈现用户首先看到的组件。
- 远程(Remote):远程是主机可以使用的另一个 Webpack 构建。它严格地可以是远程或主机。远程的主要功能是向容器公开可供使用的模块。
plugins: [
new container.ModuleFederationPlugin({
remotes: {
app_two: 'app_two'
}
})
]
- 双向主机(Bidirectional host):双向主机可以使用其他应用程序或被其他应用程序使用。因此,这个 Webpack 构建或捆绑包可以在运行时作为远程或主机的角色。
- 供应商联邦(Vendor Federation):供应商联邦是解决微前端架构中一个重要性能问题的关键功能。无论模块从何处加载,它都可以在运行时声明性地共享远程或主机的全部或部分 npm 模块。
配置选项
通过 ModuleFederationPlugin,构建可以在运行时既使用其他构建提供的模块,又向其他构建提供模块。由于模块联邦是基于配置的,因此你需要熟悉几个关键的配置选项:
- library:library 包含一个名称(库的名称)和类型选项。它有助于决定如何检索和存储公开的代码。
- name:name 配置选项唯一地标识容器。
plugins: [
new container.ModuleFederationPlugin({
name: 'shell',
})
]
};
- filename:这确定输出捆绑包的文件名。
plugins: [
new container.ModuleFederationPlugin({
filename: 'shell/remoteShop.js'
})
]
- exposes:通过模块联邦,你还可以共享文件类型,除了模块。此配置选项表示容器公开的文件或模块的路径。
- shared:这是一个重要的配置选项,允许你共享依赖于公开的模块的库以使其运行。
除了前面的配置选项,你还可能遇到其他一些选项,如 singleton、strictVersion 和 eager。
模块联邦是如何工作的?
ModuleFederationPlugin 通过提供模块的暴露和消费来实现模块联邦。
下面是一个示例代码块,展示了一个应用程序如何暴露其 AppContainer 托管 react 和 react-dom。由于共享的模块,远程应用程序将仅下载所需的应用程序代码,而不会下载共享的模块。
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
new ModuleFederationPlugin({
name: 'app_one',
library: { type: 'global', name: 'app_a' },
remotes: {
app_three: 'app_three',
app_two: 'app_two'
},
exposes: {
AppContainer: './src/App'
},
shared: ['react', 'react-dom']
})
你可以在这里找到更多关于如何在 React、Vue 和 Angular 中实现模块联邦的信息和示例。
模块联邦的优点
- 使用 shared 选项可以最小化依赖重复,因为远程依赖于主机的依赖项。如果主机缺少依赖项,远程应用程序将仅在需要时下载其依赖项。
- 可以进行 服务器端渲染,因为模块联邦可以在任何环境中工作。
- 增强了构建性能,因为模块联邦支持微前端方法,允许不同团队同时在一个较大的应用程序上进行独立的构建和部署。
- 模块联邦支持 惰性加载捆绑包,仅在需要时加载模块,从而提高了 Web 性能。
- 模块联邦管理共享依赖项的依赖图。即使出现网络故障等问题,它也有助于下载必要的依赖项。
- 改善用户体验和开发人员体验。
模块联邦的缺点
- 学习成本:对于团队中没有经验的开发人员,学习和理解 Module Federation 可能需要一些时间。
- 版本管理: 当多个子应用共享同一个模块时,确保它们的模块版本保持一致可能会变得复杂。
- 性能影响:可能会导致加载延迟,特别在多个子应用之间进行频繁的模块切换时,可能会影响用户体验。
- 跨域问题: 子应用之间可能存在跨域访问的问题,需要适当的配置。
- 复杂性: 使用 Module Federation 可能会增加一定的配置和复杂性。
- 生态系统支持:对环境要求略高,需要使用 Webpack5,旧项目改造成本大。
总结
Webpack 模块联邦是一个功能强大的特性,它使得在运行时加载单独编译的应用程序成为可能,并允许共享常用依赖项。凭借其广泛的好处和运行时集成能力,模块联邦是微前端和插件系统的重要功能。
这是一个非常有益的解决方案,特别是在共享代码在独立应用程序之间扩展的可扩展性方面,这将改善整体性能。
我希望本文帮助你了解 Webpack 模块联邦以及如何在项目中有效利用它。
评论 (0)