React微前端Module Federation下HashRouter跨域报错排查求助
微前端HashRouter配置问题排查与解决
问题背景
使用React 17 + @craco/craco 7.0.0 + Module Federation搭建1主1子的微前端架构,期望主、子应用均使用HashRouter。但子应用切换为HashRouter后,主应用抛出跨域相关错误:
Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development.
子应用使用BrowserRouter时,可正常访问http://localhost:3000/#/myinq-ui并渲染组件。
核心原因分析
- 路由上下文冲突:子应用暴露的组件中嵌套了自己的HashRouter,而主应用已经存在HashRouter,多层Router嵌套会导致React路由上下文混乱,开发环境下由于Module Federation的跨域加载特性,React将真实错误包装为跨域错误抛出。
- 主应用路由写法错误:React Router v6已废弃
exact属性,且Route必须包裹在Routes组件内,旧写法会导致路由匹配异常。 - 依赖未共享:主、子应用未共享
react-router-dom依赖,可能导致多实例冲突。
具体解决方案
1. 改造子应用:区分独立运行与微前端嵌入场景
子应用的BootstrapApp需要判断是否在微前端环境下运行,仅在独立运行时渲染HashRouter,被主应用加载时只返回组件内容(不包含Router)。
修改子应用BootstrapApp.js:
import { Route, Routes, HashRouter as Router } from 'react-router-dom'; import App from './App'; import { createToolkitTheme } from '@mui/material/styles'; import { ThemeProvider } from '@mui/material/styles'; const theme = createToolkitTheme('light'); // 判断是否为微前端嵌入环境 const isInMicroFrontend = window.parent !== window; function BootstrapApp() { if (isInMicroFrontend) { // 微前端嵌入时,不渲染Router,直接返回组件 return ( <ThemeProvider theme={theme}> <App /> </ThemeProvider> ); } // 独立运行时渲染Router return ( <Router> <ThemeProvider theme={theme}> <App /> </ThemeProvider> </Router> ); } export default BootstrapApp;
同时调整子应用App.js的路由规则:
import { Route, Routes } from "react-router-dom"; import MyInq from "./my-inq/MyInq"; function App() { return ( <> <div> <Routes> {/* 独立运行时匹配根路径 */} <Route path="/*" element={<MyInq />} /> {/* 兼容微前端嵌入时的路由前缀 */} <Route path="/myinq-ui/*" element={<MyInq />} /> </Routes> </div> </> ); } export default App;
2. 修正主应用路由配置
主应用使用React Router v6正确写法,将Route包裹在Routes内,移除废弃的exact属性,改用Link避免页面刷新。
修改主应用App.js:
import { Route, Routes, Link } from 'react-router-dom'; import { ThemeProvider } from '@mui/material/styles'; import { createToolkitTheme } from '@mui/material/styles'; import MyInqWrapper from './MyInqWrapper'; const theme = createToolkitTheme('light'); function App() { return ( <ThemeProvider theme={theme}> <div>HOST APP: <br /></div> <Link to="#/myinq-ui">Link to child app</Link> <Routes> <Route path="/myinq-ui/*" element={<MyInqWrapper />} /> </Routes> </ThemeProvider> ); } export default App;
3. 共享react-router-dom依赖
在主、子应用的modulefederation.config.js中添加共享依赖,确保双方使用同一实例:
子应用modulefederation.config.js:
const deps = require("./package.json").dependencies; module.exports = { name: "myInqMfe", exposes: { "./MyInq": "./src/components/my-inq/MyInq", }, filename: "remoteEntry.js", shared: { react: { singleton: true, requiredVersion: deps.react }, "react-dom": { singleton: true, requiredVersion: deps["react-dom"] }, "react-router-dom": { singleton: true, requiredVersion: deps["react-router-dom"] } }, };
主应用modulefederation.config.js:
const { dependencies } = require('./package.json'); module.exports = { name: "host", remotes: { myInqMfe: "myInqMfe@http://localhost:3001/remoteEntry.js" }, filename: "remoteEntry.js", shared: { react: { singleton: true, requiredVersion: dependencies.react }, "react-dom": { singleton: true, requiredVersion: dependencies["react-dom"] }, "react-router-dom": { singleton: true, requiredVersion: dependencies["react-router-dom"] } }, };
验证步骤
- 重启主、子应用开发服务
- 访问主应用
http://localhost:3000,点击跳转链接到#/myinq-ui - 子应用组件应正常渲染,无跨域错误抛出
内容的提问来源于stack exchange,提问作者copenndthagen
相关产品推荐
相关产品推荐

