使用vite-plugin-federation拆分设计系统Chunk引发react/jsx-runtime异常
问题场景
我正在使用@originjs/vite-plugin-federation实现微前端架构,远程应用暴露的组件依赖共享的@mds-inc/design-system设计系统包。相关配置如下:
远程应用Vite配置(federation部分)
federation({ name: 'reserve', filename: 'remoteEntry.js', exposes: { './ReserveButton': './src/ReserveButton.tsx', './ReserveNotice': './src/components/common/Notice.tsx', './ReserveNumberCircle': './src/components/common/NumberCircle.tsx', './ReserveTwoButton': './src/components/common/TwoButton.tsx', }, shared: ['react', 'react-dom', '@mds-inc/design-system'], })
远程应用rollupOptions的manualChunks配置
rollupOptions: { output: { format: 'es', manualChunks(id: string) { if (id.includes('node_modules/react/') || id.includes('node_modules/react-dom/')) { return '@react-vendor'; } if (id.includes('node_modules/@mds-inc/design-system') && id.includes('.css')) { return '@MDS-style'; } if (id.includes('node_modules/@mds-inc/design-system')) { return '@MDS'; } return null; } } }
宿主应用Vite配置
import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import federation from "@originjs/vite-plugin-federation"; export default defineConfig(() => { return { plugins: [ react(), federation({ name: "host", remotes: { task: "http://localhost:3001/dist/assets/remoteEntry.js", reserve: "http://mytask.wiro.kr:5001/dist/assets/remoteEntry.js", }, shared: ["react", "react-dom", "@mds-inc/design-system"], }), ], build: { target: "esnext", minify: false, cssCodeSplit: false, }, }; });
遇到的问题
启用上述@MDS拆分规则时,宿主应用运行时抛出错误:TypeError: Cannot read properties of undefined (reading 'jsx');注释该规则后恢复正常,但设计系统的Chunk拆分是业务必需的。
疑问
- 为何拆分设计系统Chunk会引发该异常?
- 如何正确配置Chunk拆分与Module Federation,实现设计系统的共享?
原因分析
手动拆分@mds-inc/design-system的JS代码为独立Chunk,会破坏Module Federation的共享依赖管理逻辑:
- Module Federation会将标记为
shared的模块处理为共享模块,在远程应用和宿主应用之间复用同一实例。但手动拆分后,该模块会被当作普通独立Chunk打包,失去了MF的共享标记。 @mds-inc/design-system内部依赖React的jsx导出,手动拆分后,远程应用的组件加载时无法正确关联到宿主提供的共享React实例,导致React相关对象未初始化,最终抛出读取jsx属性的undefined错误。
解决方案
1. 调整manualChunks规则,保留CSS拆分、移除共享依赖的JS拆分
让Module Federation自动处理@mds-inc/design-system的共享打包逻辑,仅保留其CSS部分的手动拆分:
rollupOptions: { output: { format: 'es', manualChunks(id: string) { if (id.includes('node_modules/react/') || id.includes('node_modules/react-dom/')) { return '@react-vendor'; } // 仅保留设计系统的CSS拆分 if (id.includes('node_modules/@mds-inc/design-system') && id.includes('.css')) { return '@MDS-style'; } // 其他非共享模块的拆分规则可正常添加 return null; } } }
2. 优化共享配置,保证单实例与版本一致
在远程应用和宿主应用的shared配置中,添加singleton: true确保全局仅存在一个依赖实例,同时指定requiredVersion保证版本一致:
// 远程应用和宿主应用的shared配置统一修改为 shared: { react: { singleton: true, requiredVersion: '^18.0.0' }, // 替换为实际使用的React版本 react-dom: { singleton: true, requiredVersion: '^18.0.0' }, '@mds-inc/design-system': { singleton: true, requiredVersion: '^x.x.x' } // 替换为设计系统的实际版本 }
3. 确保依赖版本完全一致
远程应用和宿主应用的package.json中,@mds-inc/design-system、react、react-dom的版本必须完全匹配,避免版本差异导致的实例冲突。
内容的提问来源于stack exchange,提问作者user22971224
相关产品推荐
相关产品推荐

