Module Federation(模块联邦、微前端)

283 阅读3分钟

个人理解

微前端指的是,生成一个js文件,html可以通过script引入该js,从而实现一个完整的逻辑的方式。比如使用npm包也可以搭建微前端,只是npm包的方式需要更新依赖版本,即每次发布,主程序需要每次更新打包。 而Federation的方式是通过webpack将应用打包为js文件,暴露出方法。其他应用引入该js文件,从而构建成完整的应用程序,且不需要重新编译部署,直接使用最新的版本。

什么是微前端

将多个独立的构建组成一个应用程序,这些独立的构建之间不应该存在依赖关系,可以单独开发和部署它们。 这通常被称作微前端,但并不仅限于此。

Federation底层概念

模块分为本地模块和远程模块:

  • 本地模块即为普通模块,是当前构建的一部分。
  • 远程模块不属于当前构建,并在运行时从所谓的容器加载。

加载远程模块被认为是异步操作。当使用远程模块时,这些异步操作将被放置在远程模块和入口之间的下一个 chunk 的加载操作中。如果没有 chunk 加载操作,就不能使用远程模块。

chunk 的加载操作通常是通过调用 import() 实现的,但也支持像 require.ensure 或 require([...]) 之类的旧语法。

高级概念

容器

每个构建都充当一个容器,简单理解为Federation生成的js文件。

模块

容器暴露出来的模块,供其他容器加载的具体内容,简单理解为js文件中暴露出来的东西

remote

remote指加载对应容器的地址,一般是url,如

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'host',
      remotes: {
        app1: 'app1@http://localhost:3001/remoteEntry.js',
      },
    }),
  ],
}

remote配置可以接受Promise,可动态的修改对应的远程容器,但是该Promise必须resolve 一个包含 get/init API 的对象

原理

容器接口支持 get  和 init 方法。 init 是一个兼容 async 的方法,调用时,只含有一个参数:共享作用域对象(shared scope object)。此对象在远程容器中用作共享作用域,并由 host 提供的模块填充。 可以利用它在运行时动态地将远程容器连接到 host 容器。

(async () => {
  // 初始化共享作用域(shared scope)用提供的已知此构建和所有远程的模块填充它
  await __webpack_init_sharing__('default');
  const container = window.someContainer; // 或从其他地方获取容器
  // 初始化容器 它可能提供共享模块
  await container.init(__webpack_share_scopes__.default);
  const module = await container.get('./module');
})();

容器尝试提供共享模块,但是如果共享模块已经被使用,则会发出警告,并忽略所提供的共享模块。容器仍能将其作为降级模块。

你可以通过动态加载的方式,提供一个共享模块的不同版本,从而实现 A/B 测试。