0Pricing
React Academy · 课时

MFE 之间的共享状态与路由

在微前端之间共享全局事件总线或 Context,并协调客户端路由。

MFE 之间的共享状态与路由 是 CoddyKit 上的免费 React Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。

状态共享的挑战

位于不同捆绑包中的微前端无法直接共享 React 状态或上下文。它们需要采用替代策略:自定义事件、共享存储、URL 或发布/订阅事件总线。

浏览器自定义事件

使用浏览器的 CustomEvent API 作为微前端之间的简单事件总线,同时避免让它们彼此耦合。

// Remote emits:
window.dispatchEvent(new CustomEvent('cart:add', { detail: { productId: '123' } }));

// Host listens:
useEffect(() => {
  const handler = (e: CustomEvent) => addToCart(e.detail.productId);
  window.addEventListener('cart:add', handler);
  return () => window.removeEventListener('cart:add', handler);
}, []);

共享事件总线库

通过模块联邦或由 URL 加载的单例来共享一个小型发布/订阅库,可以为所有 MFE 提供可访问的类型化事件总线。

// Singleton event bus
const bus = {
  listeners: new Map<string, Function[]>(),
  emit(event: string, data: unknown) {
    this.listeners.get(event)?.forEach(fn => fn(data));
  },
  on(event: string, fn: Function) {
    if (!this.listeners.has(event)) this.listeners.set(event, []);
    this.listeners.get(event)!.push(fn);
    return () => this.off(event, fn);
  },
  off(event: string, fn: Function) {
    const list = this.listeners.get(event) || [];
    this.listeners.set(event, list.filter(f => f !== fn));
  },
};
export default bus;

作为共享状态的 URL

URL(路径 + 查询参数)天然由所有 MFE 共享。您可以使用它保存导航状态,例如选中的项目、当前标签页或筛选值。

// Remote reads from URL:
const params = new URLSearchParams(window.location.search);
const productId = params.get('product');

// Remote navigates via history API (or exposes a navigate callback from host):
window.history.pushState({}, '', '/products?product=456');

路由架构

通常由外壳/主应用负责顶层路由。远程微前端通过属性接收当前路径和 navigate 回调。

// Host passes routing control to remote:
<RemoteProductsApp
  basepath="/products"
  navigate={(path) => router.push(path)}
/>

// Remote uses basepath for its internal router:
<BrowserRouter basename={basepath}>
  <Routes>...</Routes>
</BrowserRouter>

模块联邦中的 React Router

每个 MFE 都可以运行自己的 React Router,并将其作用域限定在基础路径下。主应用路由负责顶层导航,而每个远程应用独立负责自己的子导航。

// Remote App component:
export function ProductsApp({ basepath = '/products' }) {
  return (
    <BrowserRouter basename={basepath}>
      <Routes>
        <Route path="/" element={<ProductList />} />
        <Route path="/:id" element={<ProductDetail />} />
      </Routes>
    </BrowserRouter>
  );
}

共享身份验证状态

身份验证状态(用户、令牌)通常由外壳负责管理,然后作为属性传递给远程应用,或通过共享的单例存储暴露。

// Host provides auth via props:
<RemoteCheckout
  userId={currentUser.id}
  token={accessToken}
  onLogout={handleLogout}
/>

使用 Zustand 作为共享存储

通过模块联邦以单例方式共享 Zustand 存储时,所有 MFE 都会从内存中的同一个存储实例读取数据。

// shared/store.ts (exposed as singleton)
import { create } from 'zustand';
export const useCartStore = create(set => ({
  items: [],
  addItem: (item) => set(state => ({ items: [...state.items, item] })),
}));

// Configured as singleton in MF shared config

跨 MFE 通信反模式

请避免:深层嵌套的回调链、共享内部组件状态,或紧密依赖另一个 MFE 的内部 API。请将通信限制为粗粒度事件和公共契约。

测试跨 MFE 交互

请将事件契约(事件名称、数据结构)与 UI 分开测试。使用契约测试验证生产者和消费者是否同意事件模式。

快速检查

在不让多个微前端彼此耦合的情况下,共享导航/筛选状态的最简单方式是什么?

回顾

您可以通过自定义事件、单例事件总线、URL 或共享存储(Zustand/单例)在 MFE 之间共享状态。外壳负责顶层路由,并将基础路径 + navigate 传递给远程应用。请将跨 MFE 契约保持为粗粒度且具有良好类型定义的形式。

常见问题解答

「MFE 之间的共享状态与路由」课时是免费的吗?

是的 — 「MFE 之间的共享状态与路由」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。

「MFE 之间的共享状态与路由」这节课中我会学到什么?

在微前端之间共享全局事件总线或 Context,并协调客户端路由。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 React Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「MFE 之间的共享状态与路由」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 React Academy 课中编写并运行代码吗?

能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 微前端概念与权衡
  2. 使用 Webpack 5 的 Module Federation
  3. MFE 之间的共享状态与路由
  4. MFE 的独立部署与 CI 流水线
← 返回 React Academy