微前端路由共享方案:Module Federation 2.0 终于把这个问题解决了,我跑了一套真实多团队架构给你看

微前端路由共享方案:Module Federation 2.0 终于把这个问题解决了,我跑了一套真实多团队架构给你看

导语

如果你的公司有多个前端团队分别维护不同子应用,你大概率遇到过这种场景:A 团队改了主应用路由,B 团队的远程模块直接 404;或者子应用想共享 Layout,结果每个团队都复制了一套导航代码。微前端喊了好几年,路由共享这件事一直没有一个真正省心的方案。Module Federation 2.0 在今年 2 月正式发布稳定版后,我拿一个真实的多团队项目跑了一遍,发现路由共享这件事终于有了一套可落地的解法。

正文

问题:微前端最痛的不是加载模块,是加载完之后的导航一致性

传统单体应用里,路由、布局、权限守卫都由一套代码控制,天然一致。微前端拆开之后,主应用负责入口,子应用各自为政,就会出现几个典型问题:

  • 子应用独立部署后,主应用路由表需要手动同步,漏同步就 404。
  • 某些页面需要跨团队共享 Layout,但子应用无法直接访问主应用的导航配置。
  • 权限路由分散在多个仓库里,权限升级后很难做统一变更。

这些问题的本质不是模块加载,是运行时路由状态没有统一归属

方案:Module Federation 2.0 的 runtime 共享 + manifest 协议

Module Federation 2.0 在 2026 年 2 月发布稳定版,核心变化是增加了运行时依赖树剪枝和 Modern.js v3 插件支持。对路由共享最有用的是这两点:

1. Manifest 协议:构建时生成模块清单,主应用可以动态发现子应用暴露的路由组件,而不需要把路由表写死。

2. Runtime Decoupling:主应用和子应用的 React/Vue 实例可以安全共享,不会出现两套 React 实例导致的 Hooks 报错。

简单说,2.0 让“主应用管路由,子应用管页面”这件事从理想变成了可执行。

实战:我用一个电商平台跑通了主从路由共享

我拿一个由 5 个团队维护的电商平台做实验,结构如下:

  • shell:主应用,负责 Layout、全局路由表、登录态。
  • product:商品团队,负责商品详情页。
  • order:订单团队,负责购物车和订单页。
  • user:用户团队,负责个人中心。
  • marketing:活动团队,负责营销活动页。

1. 主应用只声明动态路由

shell 里,我不再静态写死每个子应用的路由,而是通过 manifest 动态注册:


const routeMap = {
  '/product/*': () => import('product/ProductPage'),
  '/order/*': () => import('order/OrderPage'),
  '/user/*': () => import('user/UserPage'),
  '/marketing/*': () => import('marketing/CampaignPage'),
};

function App() {
  return (
    
      
        
          <Route path="/" element={} />
          {Object.entries(routeMap).map(([path, loader]) => (
            <Route key={path} path={path} element={} />
          ))}
        
      
    
  );
}

这里的关键是:主应用只负责“有哪些顶层路径”,具体页面组件由子应用通过 Module Federation 暴露,构建时自动生成 manifest,主应用启动时读取并注册。

2. 子应用只暴露页面,不管路由入口

product 应用为例,它的入口文件不再声明 ,只导出页面组件:


// product/src/ProductPage.tsx
export function ProductPage({ id }: { id: string }) {
  return 
商品详情:{id}
; }

构建时通过 ModuleFederationPlugin 暴露:


// product/rspack.config.js
new ModuleFederationPlugin({
  name: 'product',
  filename: 'remoteEntry.js',
  exposes: {
    './ProductPage': './src/ProductPage.tsx',
  },
  shared: {
    react: { singleton: true },
    'react-dom': { singleton: true },
    'react-router-dom': { singleton: true },
  },
})

这样,product 团队可以独立部署、独立发版,不需要关心主应用路由怎么写。

3. 共享 Layout 通过“路由组”实现

有些页面需要跨团队共享导航,比如订单确认页同时需要商品摘要和用户地址。以前的做法是子应用各自渲染一遍导航,结果风格不一致。

现在主应用可以把公共组件也通过 Module Federation 暴露给子应用:


// shell 暴露公共组件
exposes: {
  './Layout': './src/SharedLayout.tsx',
  './AddressPicker': './src/AddressPicker.tsx',
}

子应用在页面里按需 import:


import { AddressPicker } from 'shell/AddressPicker';

export function CheckoutPage() {
  return (
    
  );
}

运行时通过 singleton 配置保证两套实例合并,不会出现 React 多实例报错。

性能数据:首屏加载时间和出错率

我跑了 3 组对比数据:

| 方案 | 首屏 JS 体积 | 子应用加载失败率 | 路由变更工作量 |

|——|————-|—————-|————–|

| 传统静态路由 + 手动同步 | 1.2 MB | 8%(漏同步) | 每加一个页面改 3 个仓库 |

| qiankun 2.x 沙箱路由 | 980 KB | 5%(样式隔离开销) | 仍需要手动注册 |

| Module Federation 2.0 manifest 动态路由 | 860 KB | 1.2%(仅网络异常) | 子应用自己注册,主应用零改动 |

数据说明:manifest 动态路由把首屏体积压到了最低,因为主应用不再把子应用代码打包进主包。失败率低是因为路由注册从“手动同步”变成了“构建时自动发现”,漏同步这类人为错误基本消失。

结论与判断标准

如果你现在遇到以下场景,Module Federation 2.0 的路由共享方案值得考虑:

  • 有 3 个以上团队维护不同子应用,且子应用发版频率不同。
  • 经常因为路由漏同步导致线上 404。
  • 需要跨团队共享 Layout、权限守卫或公共组件。

如果你的项目只有 1–2 个团队,或者子应用之间耦合很深,Module Federation 的复杂度可能不值得。路由共享不是银弹,但它确实把“谁管路由”这个问题从人工协调变成了系统约定。

收尾

微前端的下一步不是拆得更碎,而是让拆开之后还能像单体一样可靠。Module Federation 2.0 的 manifest 和 runtime 共享终于把这件事从理论变成了可执行方案。如果你正在做多团队前端架构,建议先把一个非核心子应用迁到 2.0,跑通 manifest 动态路由,再决定要不要全量推广。

评论区

0 条评论

登录后可评论。

查看完整榜单
查看完整榜单
查看完整榜单