资讯动态

module-federation-examples 实战:用 @module-federation/typescript 为 Module Federation 远程模块“流式”生成类型

发布时间:2026/10/16 5:40:02 来源:尧图企业网站定制
示例工程【免费下载链接】module-federation-examplesImplementation examples of module federation , by the creators of module federation项目地址https://gitcode.com/gh_mirrors/mo/module-federation-examples点击查看免费下载本篇技术指南以 typescript 示例 为主体讲解如何在 host/remote 架构中基于 TypeScript 构建两个相互联动的 Webpack 应用并通过module-federation/typescript插件在启动时自动生成、下发远程模块的类型声明Type Streaming。读完本文你将掌握FederatedTypesPlugin的完整配置方式、mf-types目录的生成原理以及如何在宿主应用中安全地消费带类型约束的联邦模块。示例概览host/remote 类型流式下发该示例是 module-federation-examples 仓库中一个经典的“基础 host/remote TypeScript”演示两个独立的 React 应用app1宿主端口 3001与app2远程端口 3002app2通过 Module Federation 暴露Button组件app1在运行时以懒加载方式消费它。与传统联邦方案最大的差异在于类型处理app2暴露的Button组件带有完整的 TypeScript 类型size: small | large而app1在代码中通过../mf-types/Button直接引用该类型的声明文件从而在编辑器中获得与本地模块一致的自动补全和类型检查体验——这就是 README 中提到的 “streams types”类型流式下发。整个示例由以下目录构成从仓库根目录起typescript/app1宿主应用host消费远程组件端口 3001typescript/app2远程应用remote暴露Button组件端口 3002typescript/app1/mf-types由插件自动生成的远程类型声明目录typescript/e2e/tests/commonChecks.spec.tsPlaywright 端到端校验用例typescript/package.json示例级脚本使用 pnpm workspace 串联两个应用。安装引入 module-federation/typescript按 README 的指引核心依赖通过 npm 安装$ npm i module-federation/typescript在当前仓库中app1与app2均将该包声明为运行时依赖版本为3.1.3见 app1/package.json 与 app2/package.json同时搭配module-federation/enhanced/webpack的ModuleFederationPlugin一起使用。此外两个应用还共享一套 React 18 依赖react18.3.1、react-dom18.3.1并通过shared配置实现单例共享。运行演示一条命令拉起两个应用在typescript目录或仓库根目录执行pnpm run start该命令会同时构建并启动app1与app2分别运行于 3001、3002 端口随后可访问http://localhost:3001/ —— 宿主应用app1页面中会渲染两个来自app2的远程按钮大/小两种尺寸http://localhost:3002/ —— 远程应用app2页面中渲染一个本地的Small Button。命令的底层实现见 typescript/package.json 的start脚本pnpm --filter typescript_* --parallel start即通过 pnpm workspace 并行执行两个包名以typescript_开头的应用的startwebpack-cli serve。构建产物可分别通过pnpm --filter typescript_app1 serve与pnpm --filter typescript_app2 serve以静态方式托管在对应端口。核心配置ModuleFederationPlugin 与 FederatedTypesPlugin 双插件协作类型流式的关键在 app1/webpack.config.js 与 app2/webpack.config.js 中两个插件接收同一份 federation 配置。远程端app2的配置如下摘录关键部分new ModuleFederationPlugin({ experiments: { asyncStartup: true }, name: app2, shareStrategy: loaded-first, filename: remoteEntry.js, exposes: { ./Button: ./src/Button, }, shared: [ { react: { singleton: true, requiredVersion: pkg.dependencies.react } }, { react-dom: { singleton: true, requiredVersion: pkg.dependencies[react-dom] } }, ], }), new FederatedTypesPlugin({ disableDownloadingRemoteTypes: true, federationConfig: { name: app2, filename: remoteEntry.js, exposes: { ./Button: ./src/Button, }, shared: [ { react: { singleton: true, requiredVersion: pkg.dependencies.react } }, { react-dom: { singleton: true, requiredVersion: pkg.dependencies[react-dom] } }, ], }, }),宿主端app1的配置与之对称但多了remotes指向远程入口remotes: { app2: app2http://localhost:3002/remoteEntry.js, },关键配置项说明配置项取值作用nameapp1/app2联邦应用唯一标识也作为远程引用时的命名空间filenameremoteEntry.js远程入口文件名宿主通过app2http://localhost:3002/remoteEntry.js引用exposes./Button: ./src/Button远程端暴露的模块映射仅app2需要remotesapp2http://localhost:3002/remoteEntry.js宿主端声明的远程依赖仅app1需要experiments.asyncStartuptrue异步启动配合远程类型加载避免启动竞态shareStrategyloaded-first共享依赖加载策略优先使用先加载的版本shared[].singletontrue将 react / react-dom 设为单例避免双 React 实例shared[].requiredVersionpkg.dependencies.react从package.json读取版本约束实现版本协商disableDownloadingRemoteTypestrue关闭“从远程下载类型”通道由构建期类型提取代替值得注意的两点其一FederatedTypesPlugin的federationConfig内容与ModuleFederationPlugin完全一致这是为了让类型插件能够独立解析exposes/remotes结构其二disableDownloadingRemoteTypes: true意味着类型不依赖运行时从远程拉取而是由插件在构建/启动阶段从本地源码提取生成。从源码结构看类型生成机制从 typescript/app1/mf-types 目录可以看到生成的产物结构mf-types/ └── app2/ ├── Button.d.ts # 汇总入口 └── _types/ └── Button.d.ts # 实际类型声明其中_types/Button.d.ts的内容即为从 app2/src/Button.tsx 提取出的声明import React from react; type ButtonProps { size: small | large; }; declare const Button: React.FCButtonProps; export default Button;而 app1/mf-types/app2/Button.d.ts 仅做转发export * from ./_types/Button; export { default } from ./_types/Button;该目录的生成时机在 app1/src/App.tsx 的注释中有明确说明“mf-typesdirectory is autogenerated when you start the server”即启动 dev server 时插件自动生成并持续更新。仓库中已提交了一份生成结果见 typescript/app1/mf-types/app2/_types/Button.d.ts便于读者直接观察产物形态。让 TypeScript 认识 mf-typestsconfig paths 映射生成好的类型目录并不会被 TypeScript 自动发现需要借助路径映射。两个应用的 tsconfig.json 都做了如下配置{ compilerOptions: { sourceMap: true, strict: true, jsx: react-jsx, baseUrl: ., paths: { *: [./mf-types/*] } }, include: [src/**/*] }paths将任意模块名先尝试解析到./mf-types/*于是宿主代码中形如import RemoteButtonType from ../mf-types/Button的导入即可命中mf-types/Button.d.ts该文件在app1侧由插件生成汇总入口实际内容可从 typescript/app1/mf-types/app2/Button.d.ts 追溯。strict: true保证远程组件的类型检查与本地组件同等严格。宿主消费懒加载 类型断言双保险app1/src/App.tsx 展示了标准的安全消费写法import React from react; // mf-types directory is autogenerated when you start the server import RemoteButtonType from ../mf-types/Button; // ts-expect-error app2/Button is a federated module. const RemoteButton React.lazy(() import(app2/Button)) as unknown as typeof RemoteButtonType; const App () ( div h1Typescript/h1 h2App 1/h2 React.Suspense fallbackLoading Button RemoteButton sizelarge / br / RemoteButton sizesmall / /React.Suspense /div ); export default App;这里有三个值得注意的细节运行时引用与类型引用分离import(app2/Button)是 Webpack 运行时层面的联邦模块加载../mf-types/Button是编译期类型来源。二者通过as unknown as typeof RemoteButtonType桥接既保持运行时懒加载又获得完整类型。ts-expect-error抑制提示由于app2/Button是联邦远程模块TypeScript 编译期无法直接解析其模块声明此处用ts-expect-error显式标注这一预期内的报错并避免误伤其他真实错误。类型约束即时生效RemoteButton被断言为React.FCButtonProps后sizelarge与sizesmall均被类型系统校验一旦传入非法值如sizemedium编辑器会立即给出类型错误——这正是类型流式的核心价值。远程端 app2/src/App.tsx 则直接使用本地组件import React from react; import LocalButton from ./Button; const App () ( div h1Typescript/h1 h2App 2/h2 LocalButton sizesmall / /div ); export default App;两个应用共享同一个h1Typescript/h1标题与h2应用名标识便于在浏览器中直观对照。端到端验证Playwright 用例如何校验类型示例仓库为该示例提供了完整的 E2E 覆盖见 typescript/e2e/tests/commonChecks.spec.ts测试针对 3001、3002 两个端口逐一断言两个应用均渲染相同的h1Typescript/h1标题h2中显示各自的应用名App 1/App 2两个应用都可见并可用App2 Small Button只有宿主app1端口 3001渲染App2 Large Buttonapp2自身端口 3002不出现该大按钮。其中按钮文案来自 playwright-e2e/fixtures/constants.ts 的typeScriptApp.buttons配置页面结构断言与 app1/src/App.tsx 中sizelarge/sizesmall的渲染逻辑一一对应——这从测试侧验证了远程组件暴露与类型驱动的size取值是真实生效的。配套的 typescript/playwright.config.ts 负责测试前置环境先用pnpm --filter typescript_app1 build pnpm --filter typescript_app2 build完成两个应用的构建再同时启动两个静态服务端口 3001 / 3002并等待就绪后运行测试。运行方式为pnpm run e2e:ci在typescript目录下等价于pnpm exec playwright test。适用范围与注意事项包版本与生态本示例基于module-federation/typescript3.1.3、webpack5.105.3、typescript5.5.3与 React 18配置写法如experiments.asyncStartup、shareStrategy以当前仓库锁定版本为准升级大版本时需核对插件 API 变化。类型生成的触发时机mf-types目录在启动 dev server 时自动生成首次启动后宿主 IDE 才能获得完整类型提示若该目录缺失或过期重启服务即可重新生成。ts-expect-error的取舍该写法依赖“远程模块在编译期无法解析”这一前提若未来配置了远程类型解析能力需同步移除该注释避免 TypeScript 反向报错。CORS 前提两端 devServer 均配置了Access-Control-Allow-Origin: *等跨域响应头见 app1/webpack.config.js这是浏览器环境下联邦远程加载的必备条件。更多工程规范仓库内关于 E2E 测试目录结构、运行方式与最佳实践的补充说明可参考 playwright-e2e/README.md。小结本示例完整呈现了一条“远程组件暴露 → 构建期类型提取 →mf-types自动生成 → tsconfig 路径映射 → 宿主类型安全消费”的链路。与纯 JavaScript 的联邦方案相比module-federation/typescript把类型从“运行时才知道”提前到“编译期即可感知”让跨应用开发体验向单体应用看齐。若想深入对比仓库中的 typescript-monorepo、typescript-react-fallback 等示例还提供了 monorepo 与错误回退等不同场景的参考实现。赞分享示例工程【免费下载链接】module-federation-examplesImplementation examples of module federation , by the creators of module federation项目地址https://gitcode.com/gh_mirrors/mo/module-federation-examples点击查看免费下载相关推荐RK3568 刷 Armbian 家庭服务器完整指南3 步把安卓盒子改成家用小服务器RK3568 刷 Armbian 家庭服务器完整指南3 步把安卓盒子改成家用小服务器 amlogic s9xxx armbian 主打一件事给 RK3568示例工程10 分钟跑通 RealSense 深度相机从安装出图到排掉两个真实故障10 分钟跑通 RealSense 深度相机从安装出图到排掉两个真实故障 librealsense 是 RealSense 深度相机的官方开源 SDK它把相示例工程module-federation-examples 之 Vite Svelte TypeScript 远端应用remote工程实战module federation examples 之 Vite Svelte TypeScript 远端应用remote工程实战 导读 本文以示例工程上一篇深入Lime Text架构Go语言驱动的编辑器内核下一篇5分钟掌握AI多智能体金融分析TradingAgents-CN终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑