什么是 Module Federation

Module Federation 模块联邦是 webpack 5 推出的一项新特性,目的是探索一种新的能在多应用间共享代码的方式,它们可以独立开发、构建和部署。

传统的构建方式中,依赖通过 npm 分发,和应用一起打包发布。当依赖需要更新时,应用也需要重新打包发布。

相对于传统的构建方式, Module Federation 的模块不参与消费者的构建,消费者通过运行时远程加载 Module Federation 模块。

在开发体验上,消费者引用 Module Federation 模块和普通 ESM 模块没有区别。

另外, Module Federation 还有一个特性是依赖共享。模块与模块之间的共同依赖可以配置复用,例如,如果在多个模块中都用到了 Vue ,将 Vue 设置成共享依赖之后, Vue 将只会加载一次,而不是打包在各个模块中多次加载。

消费者(Consumer)指引用使用 Module Federation 模块的模块, 对应提供 Module Federation 模块的模块称之为生产者(Provider)。一个 Module Federation 模块既可以是生产者也可以是消费者。

Module Federation 2.0 和 webpack5 Module Federation

Module Federation 2.0 是在 webpack5 Module Federation 的基础上进一步发展和优化的。

  1. 生态系统

Module Federation 2.0 支持更多的构建工具和框架,除了提供了对 webpack 的支持,还提供了 Vite, Rspack, Rsbuild 的支持。

  1. 扩展性

Module Federation 2.0 提供了运行时插件系统,允许开发者实现插件在运行时改变模块加载的默认行为和添加额外功能。

官方提供了一个插件示例 @module-federation/retry-plugin ,用于资源加载失败时进行重试,提高资源加载的成功率。
  1. 开发体验

Module Federation 2.0 提供了对动态 ts 类型的支持,启动开发服务后插件会自动拉取模块的类型定义文件,并支持热重载。

提供了 Chrome Devtool ,支持 Module Federation 代理功能,将线上页面中的 Module Federation 代理到用户本地的 Module Federation ,还支持查看模块依赖信息。
通过这些功能,可以方便地在开发和生产环境中更有效地管理和调试 Module Federation 模块。

Module Federation 2.0 和 流行微前端框架

目前流行的微前端框架有:

Module Federation 2.0 更注重动态模块加载和运行时优化,而其他微前端框架可能更侧重于静态路由和应用级别的集成。

Module Federation 2.0 目前没有提供完善的上层框架路由、js 沙箱、样式隔离等能力,当然这些都还在建设中。

目前流行的微前端框架主要的解题思路是将多个应用强行合并在一起,然后解决相互之间的冲突问题。
实现上在我看来都比较 hack ,做了大量的兼容处理,当然或多或少还是有些特殊情况难以处理,所以技术选型之前要有这个心理预期。
当然,如果是要做存量项目的改造或多技术栈融合,考虑存量项目的迁移成本,目前来说你可能没有其他更好的选择。

Module Federation 2.0 使用

Module Federation 2.0 的开发流程:

构架插件配置示例:

// 生产者配置文件
import { defineConfig } from '@rsbuild/core';
import { pluginModuleFederation } from '@module-federation/rsbuild-plugin';

export default defineConfig({
  // ...
  plugins: [
    // ...
    pluginModuleFederation({
      // 模块名
      name: 'federation_provider',
      // 导出内容
      exposes: {
        './button': './src/button.tsx',
      },
      // 共享依赖,可以配置版本信息和兼容策略
      shared: ['react', 'react-dom'],
    }),
  ],
});
// 消费者配置文件
import { defineConfig } from '@rsbuild/core';
import { pluginModuleFederation } from '@module-federation/rsbuild-plugin';

export default defineConfig({
  // ...
  plugins: [
    // ...
    pluginModuleFederation({
      // 模块名
      name: 'federation_consumer',
      // 消费的模块信息
      remotes: {
        federation_provider:
          'federation_provider@http://localhost:3000/mf-manifest.json',
      },
      // 共享依赖,可以配置版本信息和兼容策略
      shared: ['react', 'react-dom'],
    }),
  ],
});

在消费者中使用 Module Federation:

import './App.css';
// federation_provider 提供的远程组件
import ProviderButton from 'federation_provider/button';

const App = () => {
  return (
    <div className="content">
      <h1>Rsbuild with React</h1>
      <p>Start building amazing things with Rsbuild.</p>
      <div>
        <ProviderButton />
      </div>
    </div>
  );
};

export default App;

详细上手步骤可以参考官方的 doc 和 github 上的 demo。

总结

Module Federation 还在不断地完善和建设中,虽然离真正意义上的微前端还有一定距离,但其灵活的模块共享和远程加载特性,目前来说就可以解决一些复杂前端应用架构上的问题。
比如,跨团队分模块独立开发部署,模块的版本控制和更新灰度发布等等,利用 Module Federation 都会有不错的实践空间。

大家好,我是 funkyfang,多年大厂前端一线开发经验, Vue、React、RN、小程序、2D/3D小游戏和前端工程化等领域都有丰富的实战经验。如果觉得文章还不错,希望大家 点赞、关注和转发,您的支持是我持续更新的动力。🙇🏻

本人最近空闲时间比较多,可提供免费面试指导、技术问题解答和闲聊等服务,绿泡泡搜id可以找到我

Peace & Love ❤️


funkyfang
87 声望4 粉丝

多年大厂一线前端工程师 👨🏻‍💻, Vue、React、RN、小程序、2D/3D小游戏和前端工程化等领域都有丰富的实战经验,技术栈丰富的多刀流选手。