@voidzerodev: 关于 Module Federation 的更新:我们正式推荐使用 module-federation/vite。为什么?起初我们花了数月时间探索…

X AI KOLs Following 工具

摘要

Module Federation 团队正式推荐使用 module-federation/vite 插件,而不是在 Rolldown 中构建原生的 Module Federation 支持,理由是该功能的大部分特性应当位于 JavaScript 插件层,并且与现有的 Vite 插件社区合作更为高效。

关于 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 的合作中,我们添加了更多的 bug 修复和示例。 与其重复劳动,我们不如全力合作。如果打包器中有任何阻碍,我们乐于帮助修复,但我们不会在 Rolldown 中构建单独的 MF 实现。
查看原文
查看缓存全文

缓存时间: 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-hostalpine-remoteAlpine.js
Angular (https://github.com/gioboa/module-federation-vite-examples/tree/main/angular)angular-hostangular-remoteAngular
Lit (https://github.com/gioboa/module-federation-vite-examples/tree/main/lit)lit-hostlit-remoteLit
Nuxt (https://github.com/gioboa/module-federation-vite-examples/tree/main/nuxt)nuxt-hostnuxt-remoteNuxt 4
Nx (https://github.com/gioboa/react-nx-microfrontend-demo)hostremoteReact + Nx
Preact (https://github.com/gioboa/module-federation-vite-examples/tree/main/preact)preact-hostpreact-remotePreact 10
React (https://github.com/gioboa/module-federation-vite-examples/tree/main/react)react-hostreact-remoteReact 19
Solid (https://github.com/gioboa/module-federation-vite-examples/tree/main/solid)solid-hostsolid-remoteSolid
Svelte (https://github.com/gioboa/module-federation-vite-examples/tree/main/svelte)svelte-hostsvelte-remoteSvelte 5
TanStack (https://github.com/gioboa/module-federation-vite-examples/tree/main/tanstack)tanstack-hosttanstack-remoteTanStack Router + React 19
Turborepo (https://github.com/gioboa/react-turborepo-microfrontend-demo)hostremoteReact + Turborepo
Vinext (https://github.com/gioboa/module-federation-vite-examples/tree/main/vinext)vinext-hostvinext-remoteVinext + Next 16 + React 19
Vue (https://github.com/gioboa/module-federation-vite-examples/tree/main/vue)vue-hostvue-remoteVue 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.codeSplittingbuild.rolldownOptions.output.codeSplitting 设置为 false — 它将被自动忽略codeSplitting.groups 也会被忽略,因为对共享运行时块进行分组可能会破坏 MF 初始化顺序。Module Federation 需要将 loadShareruntimeInitStatus 隔离到单独的块中,以实现正确的引导行为。

⚠️ 不支持 manualChunks

不要将此插件与 build.rollupOptions.output.manualChunksbuild.rolldownOptions.output.manualChunks 一起使用 — 它们将被自动忽略。插件自己管理运行时块图,强制自定义块分组可能会破坏 Module Federation 的引导顺序。插件会注入它需要的拆分,以便 runtimeInitStatusloadShare 保持隔离。

到目前为止一切顺利 🎉

现在您已经准备好使用 Vite 中的 Module Federation 了!

相似文章

VoidZero 即将加入 Cloudflare

Hacker News Top

Cloudflare 正在收购 VoidZero——Vite、Vitest、Rolldown 和 Oxc 背后的公司,所有团队成员将加入 Cloudflare。这些工具将继续保持开源、厂商中立和社区驱动的发展方向,Cloudflare 还承诺向 Vite 生态系统基金注资 100 万美元。