@voidzerodev: 关于 Module Federation 的更新:我们正式推荐使用 module-federation/vite。为什么?起初我们花了数月时间探索…
摘要
Module Federation 团队正式推荐使用 module-federation/vite 插件,而不是在 Rolldown 中构建原生的 Module Federation 支持,理由是该功能的大部分特性应当位于 JavaScript 插件层,并且与现有的 Vite 插件社区合作更为高效。
查看缓存全文
缓存时间: 2026/05/17 22:24
关于 Module Federation 的更新:我们正式推荐使用 module-federation/vite。为什么?首先,我们花了几个月时间探索 Rolldown 中内置的 MF 支持,甚至为 @rolldown_rs 和 @vite_js 从头重新实现了 MF 2.0。我们学到的是,不仅范围巨大,而且大多数 MF 功能不可避免地存在于 JS 插件层中,而不是打包器中。与此同时,@giorgio_boa 已经在 module-federation/vite 中提供了完整的 Vite 7/8 支持。通过与 @dalaoshv、@nstlopez、@2hea1 和 @Zackary_Chapple 的合作,添加了更多错误修复和示例。我们不再重复工作,而是全力合作。如果在打包器中存在阻碍性问题,我们乐意帮助修复,但我们不会在 Rolldown 中构建单独的 MF 实现。
module-federation/vite
来源:https://github.com/module-federation/vite
用于 Module Federation 的 Vite 插件
npm (https://www.npmjs.com/package/@module-federation/vite)
原因 🤔
如今微服务 (https://martinfowler.com/articles/microservices.html) 是一个众所周知的概念,也许您当前的公司正在使用它。您知道现在可以将类似的想法应用于前端吗?使用 Module Federation (https://blog.logrocket.com/building-micro-frontends-webpacks-module-federation/#:~:text=Module%20federation%20is%20a%20JavaScript,between%20two%20different%20application%20codebases.),您可以将单独编译和部署的代码加载到一个独特的应用程序中。此插件使 Module Federation 能够与 Vite (https://vitejs.dev/) 协同工作。
工作实现
示例位于 gioboa/module-federation-vite-examples (https://github.com/gioboa/module-federation-vite-examples):
| 示例 | 主机 | 远程 | 框架 |
|---|---|---|---|
| Alpine (https://github.com/gioboa/module-federation-vite-examples/tree/main/alpine) | alpine-host | alpine-remote | Alpine.js |
| Angular (https://github.com/gioboa/module-federation-vite-examples/tree/main/angular) | angular-host | angular-remote | Angular |
| Lit (https://github.com/gioboa/module-federation-vite-examples/tree/main/lit) | lit-host | lit-remote | Lit |
| Nuxt (https://github.com/gioboa/module-federation-vite-examples/tree/main/nuxt) | nuxt-host | nuxt-remote | Nuxt 4 |
| Nx (https://github.com/gioboa/react-nx-microfrontend-demo) | host | remote | React + Nx |
| Preact (https://github.com/gioboa/module-federation-vite-examples/tree/main/preact) | preact-host | preact-remote | Preact 10 |
| React (https://github.com/gioboa/module-federation-vite-examples/tree/main/react) | react-host | react-remote | React 19 |
| Solid (https://github.com/gioboa/module-federation-vite-examples/tree/main/solid) | solid-host | solid-remote | Solid |
| Svelte (https://github.com/gioboa/module-federation-vite-examples/tree/main/svelte) | svelte-host | svelte-remote | Svelte 5 |
| TanStack (https://github.com/gioboa/module-federation-vite-examples/tree/main/tanstack) | tanstack-host | tanstack-remote | TanStack Router + React 19 |
| Turborepo (https://github.com/gioboa/react-turborepo-microfrontend-demo) | host | remote | React + Turborepo |
| Vinext (https://github.com/gioboa/module-federation-vite-examples/tree/main/vinext) | vinext-host | vinext-remote | Vinext + Next 16 + React 19 |
| Vue (https://github.com/gioboa/module-federation-vite-examples/tree/main/vue) | vue-host | vue-remote | Vue 3 |
尝试这个将所有打包器组合在一起的疯狂示例
pnpm install
pnpm run build
pnpm run multi-example
入门指南 🚀
https://module-federation.io/guide/build-plugins/plugins-vite.html
使用 @module-federation/vite,这个过程变得非常简单,您只会发现与普通 Vite 配置的差异。
此示例使用 Vue.js (https://vuejs.org/) @module-federation/vite 配置对于不同的框架保持不变。
远程应用程序配置文件:remote/vite.config.ts
import { defineConfig } from 'vite';
import { federation } from '@module-federation/vite'; 👈
export default defineConfig({
[...]
plugins: [
[...]
federation({ 👈
name: "remote",
filename: "remoteEntry.js",
// 可选:额外的 "var" 类型 remoteEntry 文件
// 仅对于使用 "var" 的传统主机需要(remote.type = 'var')
varFilename: "varRemoteEntry.js",
exposes: {
"./remote-app": "./src/App.vue",
},
shared: ["vue"],
}),
],
server: {
origin: "http://localhost:{Your port}"
},
[...]
});
在这个远程应用配置中,我们定义了一个 remoteEntry.js 文件,它将暴露 App 组件。shared 属性确保主机和远程应用使用相同的 vue 库。
主机应用程序配置文件 host/vite.config.ts
import { defineConfig } from 'vite';
import { federation } from '@module-federation/vite'; 👈
export default defineConfig({
[...]
plugins: [
[...]
federation({ 👈
name: "host",
remotes: {
remote: {
type: "module", // 对于 Vite 远程,支持类型 "var"(默认),配合远程的 `varFilename` 选项
name: "remote",
entry: "https://[...]/remoteEntry.js",
entryGlobalName: "remote",
shareScope: "default",
},
},
filename: "remoteEntry.js",
shared: ["vue"],
// 可选参数,控制主机初始化脚本的注入位置。
// 默认情况下,它被注入到 index.html 文件中。
// 您可以将其设置为 "entry" 以改为注入到入口脚本中。
// 如果您的应用程序不从 index.html 加载,则此选项很有用。
hostInitInjectLocation: "html", // 或 "entry"
// 控制是否应将所有 CSS 资产添加到每个暴露的模块中。
// 当为 false(默认)时,插件不会处理任何 CSS 资产。
// 当为 true 时,所有 CSS 资产都会打包到每个暴露的模块中。
bundleAllCSS: false, // 或 true
// 解析模块的超时时间(秒)。
// 默认为 10 秒。
moduleParseTimeout: 10,
// 解析模块的空闲超时时间(秒)。设置后,超时
// 在每个解析的模块上重置,并且仅当在配置的持续时间内没有模块活动时才会触发。
// 对于代码库较大且总构建时间可能超过固定超时值的情况,优先使用此选项而不是 moduleParseTimeout。
moduleParseIdleTimeout: 10,
// 控制是否生成模块联邦 manifest 工件。
// 类型:boolean | object
// - false/undefined:不生成 manifest
// - true:生成 mf-manifest.json + mf-stats.json(默认名称)
// - object:覆盖 fileName/filePath 和资产分析行为
manifest: {
// 可选的运行时 manifest 输出文件名。
// 默认值:"mf-manifest.json"
fileName: "mf-manifest.json",
// 两个工件的可选输出目录/路径。
// 示例:"dist/" -> dist/mf-manifest.json + dist/mf-stats.json
filePath: "dist/",
// 如果为 true,则跳过资产分析。
// 效果:shared/exposes 从 manifest 中省略,assetAnalysis 从 stats 中省略。
// 它还会禁用用于远程的预加载助手补丁。
// 在仅为消费者的应用的 serve 模式下,除非显式设置,否则默认为 true。
disableAssetsAnalyze: false,
},
}),
],
server: {
origin: "http://localhost:{Your port}"
},
[...]
});
主机应用配置指定了自身名称、暴露的远程入口文件名 remoteEntry.js,以及重要地,要加载的远程应用的配置。您可以使用 hostInitInjectLocation 选项指定主机初始化文件的注入位置,如上例代码所述。moduleParseTimeout 选项允许您配置构建过程中等待模块解析的最长时间。moduleParseIdleTimeout 选项是一个替代方案,它会在每个解析的模块上重置计时器。仅当在配置的持续时间内没有模块活动时才会触发,这使得它适用于总构建时间超过固定超时值的大型代码库。
加载远程应用
在您的主机应用中,您现在可以使用 defineAsyncComponent 导入并使用远程应用
文件 host/src/App.vue
import { defineAsyncComponent } from "vue";
const RemoteMFE = defineAsyncComponent( 👈 () => import("remote/remote-app") );
⚠️ codeSplitting 设置由插件控制
不要将此插件与 build.rollupOptions.output.codeSplitting 或 build.rolldownOptions.output.codeSplitting 设置为 false — 它将被自动忽略。codeSplitting.groups 也会被忽略,因为对共享运行时块进行分组可能会破坏 MF 初始化顺序。Module Federation 需要将 loadShare 和 runtimeInitStatus 隔离到单独的块中,以实现正确的引导行为。
⚠️ 不支持 manualChunks
不要将此插件与 build.rollupOptions.output.manualChunks 或 build.rolldownOptions.output.manualChunks 一起使用 — 它们将被自动忽略。插件自己管理运行时块图,强制自定义块分组可能会破坏 Module Federation 的引导顺序。插件会注入它需要的拆分,以便 runtimeInitStatus 和 loadShare 保持隔离。
到目前为止一切顺利 🎉
现在您已经准备好使用 Vite 中的 Module Federation 了!
相似文章
@webfansplz:在最新的集成 Rolldown v1 的 Vite DevTools 中,我们修复了大型项目的性能问题。以下是它的运行截图…
最新的集成 Rolldown v1 的 Vite DevTools 修复了大型项目的性能问题,在拥有 30,000 多个模块的 LobeHub 上得到了演示。
VoidZero 即将加入 Cloudflare
Cloudflare 正在收购 VoidZero——Vite、Vitest、Rolldown 和 Oxc 背后的公司,所有团队成员将加入 Cloudflare。这些工具将继续保持开源、厂商中立和社区驱动的发展方向,Cloudflare 还承诺向 Vite 生态系统基金注资 100 万美元。
@voidzerodev: Rolldown 现在以 Rust crate 形式提供,并将持续在那里和 npm 上发布。
Rolldown 是一个构建工具打包器,现在以 Rust crate 形式提供,并将持续在那里和 npm 上发布。
@evanyou: 我想表达的大部分内容都在VoidZero的博客文章里。但值得再次强调:感谢@voidzerodev团队…
Vue.js和Vite的创造者尤雨溪(Evan You)在VoidZero被Cloudflare收购之际,感谢了他的团队、投资者以及Vite社区。他对这段旅程表示感激,并期待与Cloudflare继续开放开发。
@lukeed05: 为庆祝 @rolldown_rs 1.0 发布,隆重推出 `comptime`——一个受 Zig 启发的构建时评估原语,作为 Vite 和 Rolldown 插件提供……
Luke Edwards 发布了 `comptime`,这是一个受 Zig 启发的构建时评估原语,适用于 Vite 和 Rolldown,允许在构建过程中执行代码,将调用位置替换为评估后的值。