Webpack Module Federation

Flying
2020-07-02 / 0 评论 / 113 阅读 / 正在检测是否收录...

Module Federation(模块联邦)是 Webpack 5 中最令人激动的功能之一,被认为是 JavaScript 架构的变革者。它支持在 JavaScript 应用程序之间更独立、更简单地共享代码,使应用程序更具适应性和动态性。

本文将介绍什么是 Webpack 模块联邦,它是如何被使用和为什么使用它,以及通过使用它可以获得的好处。

什么是模块联邦?

Webpack 模块联邦使不同代码库之间的代码和依赖共享更加容易。该架构在运行时动态加载代码,减少了代码重复的频率,只有在需要时主应用程序才会下载缺失的依赖。

runtime-sharing.png
运行时共享

如上图,作为 Home 页面的Header组件作为生产者发布,Detail 页面在运行时可以通过模块联邦消费 Header组件,从而实现组件动态共享。

package-sharing.png
构建时共享

如上图,构建时共享是 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 模块。

concept.jpg

配置选项

通过 ModuleFederationPlugin,构建可以在运行时既使用其他构建提供的模块,又向其他构建提供模块。由于模块联邦是基于配置的,因此你需要熟悉几个关键的配置选项:

  • librarylibrary 包含一个名称(库的名称)和类型选项。它有助于决定如何检索和存储公开的代码。
  • namename 配置选项唯一地标识容器。
plugins: [
    new container.ModuleFederationPlugin({
      name: 'shell',
    })
  ]
};
  • filename:这确定输出捆绑包的文件名。
plugins: [
  new container.ModuleFederationPlugin({
    filename: 'shell/remoteShop.js'
  })
]
  • exposes:通过模块联邦,你还可以共享文件类型,除了模块。此配置选项表示容器公开的文件或模块的路径。
  • shared:这是一个重要的配置选项,允许你共享依赖于公开的模块的库以使其运行。
    除了前面的配置选项,你还可能遇到其他一些选项,如 singleton、strictVersioneager

模块联邦是如何工作的?

ModuleFederationPlugin 通过提供模块的暴露和消费来实现模块联邦。

下面是一个示例代码块,展示了一个应用程序如何暴露其 AppContainer 托管 reactreact-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

评论 (0)

取消