模块联邦
模块联邦(Module Federation) 支持不同应用在独立构建后,于运行时暴露和消费模块。当你需要确认消费者能否加载真实的生产者、解析共享依赖并正确执行暴露模块时,可以用 Rstest 测试这条联邦边界。
@module-federation/rstest 为 Rstest 构建配置模块联邦。它支持 Node 和 JSDOM 测试环境以及 Browser Mode。
安装
将 @module-federation/rstest 添加到现有 Rstest 项目。
该插件只负责配置消费远程模块的测试消费者。生产者仍需使用自己的模块联邦构建插件进行构建,例如 Rslib 的 mf 格式。
基本用法
注册 federation 插件,并使用与应用代码导入一致的生产者名称。最简单的形式是消费一个构建到本地 CommonJS 入口的 Node 生产者,不需要启动任何服务:
然后像应用代码一样,通过远程模块的标识符导入暴露模块。使用动态 import() 加载,可以让生产者容器先完成初始化:
这种方式会实际经过远程模块加载和模块联邦运行时,而不是用 mock 替换联邦边界。为了通过类型检查,在 remotes.d.ts 里声明这些远程模块:
配置远程模块
federation() 插件接受和模块联邦构建插件相同的选项:remotes、shared、remoteType 等。测试里要注意两点:
- 远程入口的目标环境。 Node 和 JSDOM 测试运行在 Rstest 的 Node runner 里,所以要指向面向 Node 的远程入口,例如
remoteEntry.cjs。Browser Mode 消费的是浏览器构建产物中的remoteEntry.js。 - HTTP 生产者。 通过 HTTP 提供的生产者写成
remote@http://localhost:3001/remoteEntry.cjs这样的地址,并设置remoteType: 'script'。服务要在测试运行前启动,见用globalSetup启动生产者。
插件和 federation 配置项的关系
federation 配置项只是 Rstest 内部的运行时兼容开关。它负责安装垫片,让模块联邦运行时能在 Rstest 的 Node worker 里加载 chunk,本身不配置任何模块联邦的内容:没有远程模块,没有暴露模块,也没有共享依赖。
federation() 插件才做真正的配置,并且在基于 Node 的测试环境下会自动打开这个开关。因此在 Node 和 JSDOM 测试里使用插件时,不需要再设置 federation: true。Browser Mode 的情况不同,见 Browser mode。
用 globalSetup 启动生产者
通过 HTTP 提供的生产者,必须在测试 worker 导入消费者应用之前就能访问。使用 globalSetup 统一启动服务,并在 teardown 里停止,不要在每个测试文件里各起一次:
Browser mode
当生产者必须在真实浏览器中运行时,先配置 Browser Mode,然后在该项目的 Rstest 配置中保留同一个 federation 插件。插件会从解析后的配置中检测 browser.enabled,改用 Web 端的模块联邦运行时,而不是 Node 专用默认值。远程入口要指向浏览器构建产物中的 remoteEntry.js:
Browser Mode 下插件不会自动打开 federation 配置项。但 globalSetup 文件始终在 Node 进程里执行,产物里同样带着模块联邦运行时,没有这个开关,globalSetup 文件一加载就会报错,生产者服务也就起不来。所以 Browser Mode 项目只要用了 globalSetup,就要手动写上 federation: true。
了解更多
federation参考文档介绍了独立配置项、CLI flag 和 Rstest 运行时行为。- Rstest 官方集成指南介绍了如何复用 Rsbuild 的模块联邦配置、插件选项和生产者构建。
- Node 示例:用 Rslib 构建的本地 CommonJS 生产者,不需要 HTTP 服务。
- Browser 示例:通过 HTTP 提供的联邦 React 组件,在 Chromium 中测试。