webpack5模块联邦对微前端架构有什么重大意义?

5,536 阅读3分钟

模块联邦

webpack作为前端工程师广泛使用的打包工具,在整个前端生态中具有不可撼动的地位。目前,在最新的webpack5版本中带来了许多新特性,其中模块联邦倍受关注。

什么是模块联邦

module federation 模块联邦,它可以让多个独立构建的应用之间,动态的调用彼此的模块。这种运行机制,可以让我们轻松的拆分应用,真正做到跨应用的模块共享。

image.png

重要概念

host: webpack构建可以是remote远程服务的提供方。

remote:也可以作为host主机的服务消费方。

bidirectional-hosts: 亦可作为双向主机,同时兼顾remote和host。

container:每个构建都充当一个容器,能够通过从对应的容器中加载模块来访问其它容器暴露出来的模块。

image.png

简单示例

app1 配置:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const { ModuleFederationPlugin } = require("webpack").container; // 通过使用webpack内置插件构建模块

module.exports = (env = {}) => ({
  // 其它 webpack 配置...
  plugins: [
    new ModuleFederationPlugin({
      name: "app1", // 当前应用的名称,需要全局维一
      filename: "remoteEntry.js", // 共享模块的入口文件
      library: { type: 'var', name: 'app1' }, // 共享模块的全局引用
      exposes: { // 导出的模块,只有在此申明的模块才可以作为远程依赖被使用
        "./Button": "./src/components/Button",
      },
      shared: ['vue', 'element-ui'] // 远程加载的模块对应的依赖使用本地项目的依赖
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "./public/index.html"),
    })
  ],
  
  devServer: {
    port: 3001,
  }
});

app2 配置:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const { ModuleFederationPlugin } = require("webpack").container; // 通过使用webpack内置插件构建模块

module.exports = (env = {}) => ({
  // 其它 webpack 配置...
  plugins: [
    new ModuleFederationPlugin({
      name: 'app2',
      filename: "remoteEntry.js",
      remotes: { // 引入远程应用的导出的模块, name@host address/filename.
        app1: 'app1@http://localhost:3001/remoteEntry.js'
      },
      shared: ['vue', 'element-ui'] // 抽离的依赖与其它应用保持一致
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "./public/index.html"),
    })
  ],
});

更多的使用案例请参考此仓库: module-federation-examplesh

微前端架构存在的问题

image.png

在当前的微前端架构中,通过了许多技术手段如应用分离、JS沙箱、CSS隔离、预加载等实现了整个架构的使用。但对于公共依赖加载目前并没有非常好的解决方案。

通常处理公共依赖的方式是使用npm,将依赖抽离作为lib公共库进行管理。应用之中使用到lib,将其安装到项目中,再通过webpack打包上线。

image.png

这种方式虽然解决了公共依赖问题,但还是需要走本地编译,无法做到项目运行时(runtime)调用。

使用webpack5模块联邦就可以解决这一问题。

将公共依赖配置成一个远程模块,子应用只需要根据需求动态加载。这种方式可以做到运行时调用,不用考虑本地编译问题。

image.png

这就衍生出一种新的应用形态——中心应用,这个应用具备模块化输出的能力,可以在线动态的分发运行时的子模块。

image.png

结语

模块联邦在一定程度上弥补了微前端架构中的不足,让微前端架构日益趋向成熟。在可以预见的未来,前端工程化将进入一个新的阶段,下一波技术浪潮将会来临。