React v18 + Router v6 + Module Federation子应用路由失效问题
解决Module Federation + React Router v6子应用路由不生效问题
核心原因
根应用已挂载BrowserRouter,子应用不能重复嵌套路由实例;同时根应用路由未正确传递子路径给子应用,导致子应用内部路由无法匹配。
解决方案步骤
1. 修正根应用路由配置
确保根应用中指向Payments子应用的路由添加通配符*,让所有/payments开头的子路径都传递给子应用处理:
// 根应用主路由文件 import { BrowserRouter, Routes, Route } from 'react-router-dom'; // 通过Module Federation引入子应用组件 import Payments from 'payments/Payments'; function RootApp() { return ( <BrowserRouter> <Routes> {/* 其他根路由 */} {/* 关键:path末尾添加*,传递子路径 */} <Route path="/payments/*" element={<Payments />} /> </Routes> </BrowserRouter> ); }
2. 子应用路由配置(无需嵌套Router)
子应用内部直接使用Routes和Route,路径使用相对路径(基于根应用的/payments路径):
// .packages/payments/src/app/Payments.jsx import { Routes, Route, Link } from 'react-router-dom'; import PaymentList from './PaymentList'; import PaymentDetail from './PaymentDetail'; export default function Payments() { return ( <div className="payments-app"> <nav> {/* 相对路径跳转 */} <Link to="list">支付列表</Link> <Link to="detail/1">支付详情(示例ID)</Link> </nav> <Routes> {/* 匹配/payments根路径 */} <Route index element={<PaymentList />} /> {/* 匹配/payments/list */} <Route path="list" element={<PaymentList />} /> {/* 匹配/payments/detail/:id */} <Route path="detail/:id" element={<PaymentDetail />} /> </Routes> </div> ); }
3. 子应用本地开发兼容(可选)
如果需要子应用单独运行开发,可在bootstrap.jsx中添加条件渲染,仅在独立运行时挂载BrowserRouter:
// .packages/payments/src/bootstrap.jsx import React from 'react'; import ReactDOM from 'react-dom/client'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Payments from './app/Payments'; // 仅当子应用独立运行时(非被根应用加载)才初始化Router if (!window.isModuleFederationHost) { const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <BrowserRouter> <Routes> <Route path="/*" element={<Payments />} /> </Routes> </BrowserRouter> </React.StrictMode> ); }
4. 验证Module Federation配置
确保子应用的webpack配置正确暴露Payments组件,且共享路由依赖避免多实例冲突:
// 子应用webpack.config.js const { ModuleFederationPlugin } = require('webpack').container; module.exports = { plugins: [ new ModuleFederationPlugin({ name: 'payments', filename: 'remoteEntry.js', exposes: { './Payments': './src/app/Payments', // 正确暴露组件路径 }, shared: { react: { singleton: true }, 'react-dom': { singleton: true }, 'react-router-dom': { singleton: true }, // 共享路由依赖,避免版本冲突 }, }), ], };
常见排查点
- 确认根应用路由的
path="/payments/*"末尾的*没有遗漏,这是传递子路径的关键 - 子应用内部路由路径不要用绝对路径(如
/list),改用相对路径(如list) - 确保
react-router-dom在Module Federation的shared配置中设为singleton: true,避免多实例冲突
内容的提问来源于stack exchange,提问作者Timur Ivanov
相关产品推荐
相关产品推荐

