跨应用 Tab 组件远程加载与路由同步:解析 comprehensive-demo-react18 的 Tabs 演示
示例工程【免费下载链接】module-federation-examplesImplementation examples of module federation , by the creators of module federation项目地址https://gitcode.com/gh_mirrors/mo/module-federation-examples点击查看免费下载comprehensive-demo-react18 是 module-federation-examples 仓库中的一个多框架综合示例其中位于 app-01/src/docs/Tabs.md 的文档完整演示了「宿主应用App #1通过 Module Federation 远程加载 App #2 的 Tabs 组件并让浏览器路由与 Tab 状态实时同步」的实战方案。本文将以该文档为主线结合仓库内真实源码与 E2E 测试逐层拆解远程 Tab 组件如何实现、如何与路由联动、如何按需懒加载第三个应用的样式化组件帮助你掌握一套可复用的「远程组件 路由同步 懒加载」联邦化开发模式。一、文档背后的演示场景App #1 中的 Routing DemoTabs.md 位于宿主应用 App #1 的文档目录中它描述了以下四个核心事实页面中的 Tab 组件是从bravo-app即 App #2运行在 3002 端口远程导入的浏览器的路由会随激活的 Tab 在/routing/foo与/routing/bar之间切换直接打开 http://localhost:3002App #2 的根页面可以看到完全相同的 Tab 组件Bar 这个 Tab 内还按需懒加载了来自 UI Library 演示App #33003 端口的 styled-componentsButton且仅在 Bar 被渲染时才加载。这正是 Module Federation 中「同一远程组件既可作为宿主页面内嵌模块、又可作为远程应用自身页面模块」的双重用法也展示了跨应用按需加载的完整链路App #1 → App #2Tabs→ App #3Button。二、文档如何在页面中呈现routing-page.jsx 与 Markdown 渲染链路Tabs.md 之所以能成为路由演示页的说明文档是因为 App #1 在构建时通过raw-loader将.md文件作为字符串导入见 app-01/webpack.config.js再由 app-01/src/Markdown.jsx 使用markdown-to-jsx渲染成 Material UI 风格的排版。路由演示页 routing-page.jsx 把「文档」与「远程组件」放在同一页面import Markdown from markdown-to-jsx; import Page from ../Page; import React from react; import Tabs from ../docs/Tabs.md; const RoutedTabs React.lazy(() import(app_02/Tabs)); const RoutingPage () ( Page titleRouting Demo Markdown{Tabs}/Markdown React.Suspense fallbackLoading Tabs... RoutedTabs / /React.Suspense /Page );这里import(app_02/Tabs)是app_02这个远程容器remote container的异步导入调用配合React.lazy与React.Suspense实现了远程组件的懒加载只有当用户进入/routing路由时Tabs 组件才会被拉取并渲染。该页面被挂载在 app-01/src/Routes.jsx 的/routing路径下。三、远程 Tab 组件的实现路由驱动切换的 Tabs.jsx文档所说的「路由随 Tab 变化」并非空话而是由 App #2 中的 Tabs.jsx 通过react-router-dom的 Hook 实现的。它用useRouteMatch()取得当前页面的基础路径在 App #1 内即/routing用useHistory()在切换 Tab 时改写 URL用useLocation()读取当前路径作为 Tab 的激活值const match useRouteMatch(); const history useHistory(); const location useLocation(); const { path: rootPath } match; const handleChange (event, newValue) { history.push(newValue); }; Tabs value{location.pathname} onChange{handleChange} Tab labelFoo value{${rootPath}/foo} / Tab labelBar value{${rootPath}/bar} / /Tabs随后通过Switch/Route将路由与内容绑定/routing精确匹配时重定向到/routing/foo/routing/foo渲染 Foo Content/routing/bar渲染 Bar Content。关键点在于这套组件并不关心自己运行在哪个应用里。它从match.path推导基础路径因此在 App #1 的/routing下表现为/routing/foo、/routing/bar而当它作为 App #2 根页面的一部分渲染时见 app-02/src/App.jsx基础路径退化为空路由就变成/foo、/bar。文档中「打开 3002 端口能看到同样的 Tab 组件」正是由此而来。四、Bar Tab 的按需懒加载跨应用加载 styled-components Button文档还强调了一个容易被忽略的细节Bar 内容里的Button来自 UI Library 演示App #3并且「仅在 Bar 被渲染时懒加载」。这在 Tabs.jsx 的顶部和 Bar 路由内均有体现const Button React.lazy(() import(app_03/Button));Bar 路由的内容中嵌套了React.SuspenseRoute path{${rootPath}/bar} Typography componentdiv Box p{3} Bar Content React.Suspense fallback{null} ButtonBar Button/Button /React.Suspense /Box /Typography /Route只有路由落在/routing/bar或 App #2 根部的/bar时app_03/Button才会被真正加载。该按钮是 app-03/src/Button.jsx 中一个典型的 styled-components 样式化组件const Button styled.button display: inline-block; border-radius: 3px; padding: 0.5rem 0; margin: 0.5rem 1rem; width: 11rem; background: palevioletred; color: white; font-size: 1rem; font-family: sans-serif; ;于是形成了「宿主 → 远程 Tab → 更远程的 Button」两级懒加载链条验证了 Module Federation 支持嵌套联邦remote 再消费 remote的能力。五、支撑这一切的联邦配置exposes、remotes 与 shared5.1 App #1宿主兼聚合方app-01/webpack.config.js 中的ModuleFederationPlugin声明了四个远程依赖其中就包含 App #2 与 App #3remotes: { app_02: app_02http://localhost:3002/remoteEntry.js, app_03: app_03http://localhost:3003/remoteEntry.js, app_04: app_04http://localhost:3004/remoteEntry.js, app_05: app_05http://localhost:3005/remoteEntry.js, },同时它以exposes对外提供./SideNav与./Page供 App #2 反向消费见下文 App #2 的 App.jsx。5.2 App #2既是被消费方又是消费方app-02/webpack.config.js 中name: app_02与filename: remoteEntry.js定义了远程容器的身份与入口文件exposes声明了对外暴露的模块exposes: { ./Dialog: ./src/Dialog, ./Tabs: ./src/Tabs, },remotes则声明了它自身的依赖——App #1 的Page组件与 App #3 的Buttonremotes: { app_01: app_01http://localhost:3001/remoteEntry.js, app_03: app_03http://localhost:3003/remoteEntry.js, },App #2 的根应用 App.jsx 正是通过import(app_01/Page)复用 App #1 的Page外壳顶栏 内容区再把本地Dialog与Tabs渲染进去从而与 App #1 的页面观感完全一致。5.3 共享依赖singleton 与 eager为避免 React 双实例问题两端配置都对核心依赖做了单例化处理。以 App #2 为例shared: { ...deps, material-ui/core: { singleton: true }, react-router-dom: { singleton: true }, react-dom: { singleton: true, requiredVersion: false, eager: true }, react: { singleton: true, requiredVersion: false, eager: true }, },singleton: true保证联邦各应用共用同一份react、react-dom、material-ui/core与react-router-dom避免 hooks 状态错乱requiredVersion: false放宽版本校验允许跨应用版本不一致时仍可共享eager: true让核心依赖在容器启动时同步就绪避免加载时序问题此外experiments: { asyncStartup: true }开启了异步启动实验特性shareStrategy: loaded-first指定共享依赖采用「先加载者优先」策略。值得说明的是App #2 同时提供了 webpack 与 rspack 两套构建配置webpack.config.js 与 rspack.config.js二者在联邦配置上保持了一致仅构建器与 loader 不同便于对比两种工具链下的联邦实现。此外两端 devServer 都开启了 CORS 头Access-Control-Allow-Origin: *这是浏览器端跨端口拉取remoteEntry.js与联邦模块的必要前提。六、文档中「路由即 URL」的可验证性Playwright E2E 测试文档所描述的行为已被仓库内的 E2E 测试固化。在 comprehensive-demo-react18/e2e/checkApp1.spec.ts 中routing page renders tabs用例完整验证了整条链路test(routing page renders tabs, async ({ page }) { await page.goto(${base}/#/routing/foo); ... await expect(page.getByRole(tab, { name: Foo })).toBeVisible(); await expect(page.getByText(Foo Content)).toBeVisible(); await page.getByRole(tab, { name: Bar }).click(); await expect(page.getByText(Bar Content)).toBeVisible(); const barButton page.getByRole(button, { name: Bar Button }); await expect(barButton).toBeVisible(); await expect(barButton).toHaveCSS(background-color, rgb(219, 112, 147)); });该用例同时断言了 Tabs.md 中的全部四段文字routingParagraphs见 checkApp1.spec.ts并验证了路由进入#/routing/foo时 Foo Tab 激活、Foo 内容可见点击 Bar Tab 后 Bar 内容可见且 Bar Button 懒加载成功rgb(219, 112, 147)正是 App #3 中palevioletred的解析结果证明远程样式化按钮确实渲染生效。同一测试文件还以{ name: Routing, hash: #/routing/foo }断言了侧边栏中 Routing 入口的链接checkApp1.spec.ts并将#/routing/foo作为文档锚点链接的一部分checkApp1.spec.ts与文档「浏览器路由是 /routing/foo|bar」的描述相互印证。七、如何运行与体验在 comprehensive-demo-react18 目录下按序执行yarn install pnpm run start随后打开 http://localhost:3001从左侧导航进入Routing页面即可复现本文所述场景再打开 http://localhost:3002 对比同一 Tabs 组件在远程应用根部的表现。整个 demo 由五个应用构成App #13001宿主外壳→ App #23002Material UI 组件提供方→ App #33003styled-components UI 库→ App #43004Svelte→ App #53005LitElement。运行 E2E 测试可执行pnpm test:e2e或使用pnpm test:e2e:ui打开交互式调试界面见 comprehensive-demo-react18/package.json。八、小结从本文可复用的三件事通过 Tabs.md 与配套源码可以提炼出三种可直接迁移到自有项目的实践远程组件的路由自适应远程组件用useRouteMatch().path而非硬编码路径推导基础路由就能在同一份代码下同时服务于宿主子路由/routing/foo与远程应用根路由/foo两级懒加载React.lazySuspense可以让「宿主 → 远程 → 再远程」的嵌套依赖按需加载配合exposes/remotes的容器声明即可实现组件级代码拆分以文档驱动演示将 Markdown 说明文件作为页面的一部分raw-loader导入 markdown-to-jsx渲染再配合同页面的可交互远程组件与 E2E 断言让「文档描述、代码实现、自动化验证」三者保持一致。如需继续深入可对照阅读同目录下的 Dialog.mdReact Portal 场景的远程 Dialog与 UiLibrary.md独立 CSS 方案下的远程 Button它们共同构成了 comprehensive-demo-react18 中「跨应用组件复用」的完整示例集。赞分享示例工程【免费下载链接】module-federation-examplesImplementation examples of module federation , by the creators of module federation项目地址https://gitcode.com/gh_mirrors/mo/module-federation-examples点击查看免费下载相关推荐跨应用远程 Tab 组件实战基于 module-federation-examples 的嵌套路由与惰性加载解析跨应用远程 Tab 组件实战基于 module federation examples 的嵌套路由与惰性加载解析 导读 本文以 module federati示例工程Module Federation 实战在 comprehensive-demo-react16 中懒加载远程 Dialog 组件并用 React Portal 渲染Module Federation 实战在 comprehensive demo react16 中懒加载远程 Dialog 组件并用 React Porta示例工程module-federation-examples 之 comprehensive-demo-react18React 18 多框架模块联邦综合演示实战指南module federation examples 之 comprehensive demo react18React 18 多框架模块联邦综合演示实战指南示例工程上一篇SubFinder跨平台兼容性终极指南Windows/macOS/Linux环境全面对比下一篇Evergreen UI自定义组件开发扩展现有组件的5种实用模式创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Grafana Mimir 中的 pflag 深度指南:POSIX/GNU 风格命令行旗标解析从入门到源码

Grafana Mimir 中的 pflag 深度指南:POSIX/GNU 风格命令行旗标解析从入门到源码

时序数据库后端数据存储可观测性云原生 【免费下载链接】mimir Grafana Mimir provides horizontally scalable, highly available, multi-tenant, long-term storage for Prometheus. 项目地址: https://gitcode.com/gh_mirrors/mimir/mimir 点击查看 免费下载 Gr…

2026/10/15 6:31:46 阅读更多 →
LBO、BBO、KTP 三种非线性晶体怎么对比选型?优缺点差异?

LBO、BBO、KTP 三种非线性晶体怎么对比选型?优缺点差异?

LBO、BBO、KTP 三大非线性晶体全面对比 优缺点 选型指南核心参数总览(1064nm,10ns 纳秒基准)对比项目KTP 磷酸钛氧钾LBO 三硼酸锂BBO 偏硼酸钡透光区间300~5500 nm160~2600 nm190~3500 nm有效非线性系数最…

2026/10/15 6:31:46 阅读更多 →
Unity/Unreal光照烘焙与探针实操指南:静态精度+动态融合

Unity/Unreal光照烘焙与探针实操指南:静态精度+动态融合

1. 项目概述:为什么“光照烘焙与探针”不是锦上添花,而是实现实时渲染真实感的分水岭“在Demo实装光照烘焙与探针”——这短短十个字,背后是一整套实时渲染管线中最具性价比的光影解决方案。我带过不少刚接触Unity或Unreal的开发者&#xff0…

2026/10/15 6:30:46 阅读更多 →

最新新闻

Studio Pro 8实战:编曲、直播机架与实时调音三合一攻略

Studio Pro 8实战:编曲、直播机架与实时调音三合一攻略

先说个真实情况:最近好几个朋友都在找“Studio Pro 8”,有的是想拿来编曲,有的是想搭直播机架,还有的只是想给唱歌效果做实时美化。我拿到这套软件在Mac和Windows两台机器上都实测了一段时间,有些体会还挺反直觉的——…

2026/10/15 7:23:56 阅读更多 →
Spring Boot会员管理系统毕设实战:从数据库设计到JWT鉴权部署

Spring Boot会员管理系统毕设实战:从数据库设计到JWT鉴权部署

“名士会所会员管理系统”,光看这个标题你可能觉得就是一个普通的Spring Boot CRUD项目,但我做完这套毕业设计源码之后最大的感受是:它其实是一个把业务复杂度控制得恰到好处的“小型企业级系统”。会所行业的会员管理,表面上只有…

2026/10/15 7:23:56 阅读更多 →
CSP-J 2024 真题 地图探险 题解(普及-)|从暴力到正解全讲一遍

CSP-J 2024 真题 地图探险 题解(普及-)|从暴力到正解全讲一遍

继续刷 CSP-J 2024 真题。这题考点是暂无评定,先把题意吃透。 题目来源:ACGO A34462 | 洛谷 P11228难度定位:普及- | 通过率:47.16% 一、题目信息 题目名称:地图探险 所属赛事:2024 …

2026/10/15 7:23:56 阅读更多 →
吊装安全生命线受力分析模块:原理与应用

吊装安全生命线受力分析模块:原理与应用

1. 吊装安全的核心防线:生命线受力分析模块解析在重型设备吊装作业现场,生命线(绳)作为最后一道安全屏障,其可靠性直接关系到高空作业人员的生命安全。传统经验判断法已无法满足现代工程对精确计算的需求,这…

2026/10/15 7:23:56 阅读更多 →
SpringBoot+MySQL实现4S店车辆租售一体化管理系统全流程拆解

SpringBoot+MySQL实现4S店车辆租售一体化管理系统全流程拆解

1. 项目概述与需求拆解1.1 这类系统到底解决了什么现实问题先聊一个我在带毕设和做外包时反复遇到的现象:很多同学一听到"汽车销售管理系统",第一反应就是"无非是车辆信息的增删改查"。但真正走进一家4S店或者二网经销商去看&#x…

2026/10/15 7:23:56 阅读更多 →
DeepSeek本地部署硬件要求与环境配置:显存估算、CUDA对齐与推理框架选型

DeepSeek本地部署硬件要求与环境配置:显存估算、CUDA对齐与推理框架选型

简介:这份PDF资料聚焦DeepSeek大模型的本地化部署,面向希望在私有环境中运行开源大模型的开发者、运维人员及企业技术团队,帮助解决硬件选型与软件环境配置两大核心难题。资源包内含1个PDF文件,大小约274KB,内容按硬件…

2026/10/15 7:22:56 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →