React 用 Module Federation 拆巨石应用:独立部署的子应用与主应用运行时组合

test12026-10-121 次阅读

为什么需要模块联邦

当多个团队在同一套 React 代码库里互相阻塞,或者一个功能上线要等整个巨石应用重新构建,模块联邦(Module Federation)能把应用拆成多个可独立构建、独立部署的子应用,在运行时由浏览器拼装。它解决的是“构建期解耦”和“运行时共享”两个痛点。

用 @module-federation/enhanced 配置主子应用

现代方案推荐 Webpack 5 内置或 Rspack 的 @module-federation/enhanced。下面是一组最小配置:子应用暴露组件,主应用远程加载。

// host 主应用:webpack/rspack 配置片段
import { ModuleFederationPlugin } from '@module-federation/enhanced';

export default {
  plugins: [
    new ModuleFederationPlugin({
      name: 'host',
      remotes: {
        cart: 'cart@https://cart.example.com/remoteEntry.js',
      },
      shared: {
        react: { singleton: true, requiredVersion: '^18.0.0' },
        'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
      },
    }),
  ],
};
// cart 子应用:暴露一个远程组件
new ModuleFederationPlugin({
  name: 'cart',
  filename: 'remoteEntry.js',
  exposes: {
    './CartButton': './src/CartButton.tsx',
  },
  shared: {
    react: { singleton: true, requiredVersion: '^18.0.0' },
    'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
  },
});

在 React 里懒加载远程组件

远程组件本质是一个异步模块,用 React.lazy 包裹即可接入 Suspense。

import { lazy, Suspense } from 'react';

const CartButton = lazy(() => import('cart/CartButton'));

export function Header() {
  return (
    <header>
      <h2>商城</h2>
      <Suspense fallback={<span>加载购物车…</span>}>
        <CartButton />
      </Suspense>
    </header>
  );
}

工程落地要点

  • shared 里给 react / react-dom 设 singleton: true,避免运行期出现两个 React 实例导致 hooks 报错。
  • 子应用独立部署后,主应用通过 remoteEntry.js 的 URL 在运行时拉取,发布子应用不需要重新构建主应用。
  • 类型共享:把子应用导出的 props 类型单独发包,或用 tsconfig paths 指向本地 dts 文件,避免主应用写错 props。
  • 版本冲突:shared 的 requiredVersion 决定主子应用能否复用同一份依赖,设置不当会静默多份打包。
T

test1

文章作者

为什么需要模块联邦 当多个团队在同一套 React 代码库里互相阻塞,或者一个功能上线要等整个巨石应用重新构建,模块联...

分类
技术
发布时间
2026-10-12
字数
约 1704 字
阅读
1 次