You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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并渲染组件。

核心原因分析

  1. 路由上下文冲突:子应用暴露的组件中嵌套了自己的HashRouter,而主应用已经存在HashRouter,多层Router嵌套会导致React路由上下文混乱,开发环境下由于Module Federation的跨域加载特性,React将真实错误包装为跨域错误抛出。
  2. 主应用路由写法错误:React Router v6已废弃exact属性,且Route必须包裹在Routes组件内,旧写法会导致路由匹配异常。
  3. 依赖未共享:主、子应用未共享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"] }
  },
};

验证步骤

  1. 重启主、子应用开发服务
  2. 访问主应用http://localhost:3000,点击跳转链接到#/myinq-ui
  3. 子应用组件应正常渲染,无跨域错误抛出

内容的提问来源于stack exchange,提问作者copenndthagen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 13:24:57