在远程模块之间共享状态和路由
在独立部署的微前端之间共享一个 React Router 实例和 Zustand 存储。
在远程模块之间共享状态和路由 是 CoddyKit 上的免费 React Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。
状态共享的挑战
每个 Module Federation 远程应用都是独立构建和部署的应用。它的状态(React useState、Context、Zustand 存储)存在于自己的 JavaScript 模块作用域中。宿主应用和远程应用不会自动共享状态,您必须明确设计共享方式。
方案一:将 URL 作为共享状态
最简单的状态共享机制就是 URL:任何远程应用都可以读取 URL 参数、查询字符串和哈希值,无需进行跨远程应用通信。这非常适合主导航状态、筛选值,以及任何应该能够加入书签并通过链接分享的状态。
方案二:使用 CustomEvents 实现松耦合
通过浏览器的 EventTarget,CustomEvents 可以让远程应用在无需直接导入的情况下进行通信。一个远程应用可以调用 window.dispatchEvent(new CustomEvent('cart:updated', { detail: cart })),而其他任何模块(宿主应用或其他远程应用)都可以使用 window.addEventListener('cart:updated', handler) 进行监听。整个过程不需要共享模块。
方案三:创建共享状态远程应用
创建一个专用的“状态远程应用”,对外提供 Zustand 或 Jotai 存储。宿主应用和其他远程应用都从这个状态远程应用导入内容,并获得同一个存储实例,因为它是共享的单例。这种方式非常适合复杂的共享状态(身份验证、购物车、用户偏好设置),但会增加部署依赖。
方案四:由宿主应用管理状态并传递回调
外壳(宿主应用)管理所有共享状态,并通过属性或 Context 将状态传递给远程应用。远程应用会接收 onCartUpdate 等回调,并将 navigate 作为属性传入。这种方式可以让状态集中在宿主应用中,但要求宿主应用了解远程应用的接口,从而形成紧耦合。
Module Federation 中的 React Router
React Router 的历史记录和位置状态由 Router 组件(BrowserRouter 或 createBrowserRouter)提供。在 Module Federation 设置中必须且只能有一个 Router;如果在每个远程应用中都放置一个 Router,就会产生多个相互竞争的路由上下文,导致导航冲突。
由宿主应用管理 Router
架构规则是:由宿主应用(外壳)提供 Router。远程应用从宿主应用接收路由属性,或直接读取 URL。远程应用绝不能创建自己的 BrowserRouter,否则会与宿主应用的 Router 冲突,导致整个应用无法正常导航。
跨远程应用共享 Context
React Context 的值与特定的 React 实例和 Context 对象绑定。要让 Context 在宿主应用和远程应用之间正常工作,双方必须从同一个来源导入同一个 Context 对象,通常是共享状态远程应用或共享工具包。React 单例可以确保同一个 Context 在所有远程应用中正常使用。
外壳架构模式
在清晰的 Module Federation 架构中,外壳(宿主应用)负责:HTML 外壳、Router 提供方、身份验证上下文、主题或设计令牌提供方,以及全局导航。远程应用负责自己的功能领域内容。外壳会将远程应用组合到布局中,而无需了解它们的实现细节。
避免紧耦合
Module Federation 中最大的问题模式就是宿主应用与远程应用紧耦合:宿主应用从远程应用导入类型,远程应用从宿主应用导入组件,或者双方共享一个必须同时更新的 npm 包。这些耦合都会违背独立部署的初衷。
通信契约
请定义宿主应用与远程应用之间的明确契约:远程组件接受的属性、它派发的 CustomEvents,以及它读取的 URL 参数。将这些契约作为共享类型包中的 TypeScript 接口记录下来。这样,各团队就可以在约定的契约范围内独立演进。
Module Federation 中 React Router 的放置位置
在 Module Federation 架构中,React Router 提供方(BrowserRouter)应该放在哪里?
课程回顾
Module Federation 远程应用之间可以通过 URL 状态(最简单)、CustomEvents(松耦合)、共享状态远程应用(集中式存储),或由宿主应用管理并通过属性传递的状态来实现状态共享。宿主应用必须管理唯一的 Router 提供方,远程应用绝不能创建自己的 Router。通过 TypeScript 接口定义清晰的通信契约,可以让团队保持解耦,实现真正的独立部署。
常见问题解答
「在远程模块之间共享状态和路由」课时是免费的吗?
是的 — 「在远程模块之间共享状态和路由」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。
「在远程模块之间共享状态和路由」这节课中我会学到什么?
在独立部署的微前端之间共享一个 React Router 实例和 Zustand 存储。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「在远程模块之间共享状态和路由」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Academy 课中编写并运行代码吗?
能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 模块联邦:动态运行时导入
- 配置宿主与远程 React 应用
- 在远程模块之间共享状态和路由
- 版本管理、部署与编排