Module Federation 常见问题如何排查和修复?
Module Federation 出问题时,表面现象通常是白屏、远程组件加载失败、依赖版本冲突或样式串了。不要一上来就改 webpack 配置,先判断问题发生在哪一段:Host 找不到 remoteEntry、remoteEntry 找不到 chunk、共享依赖初始化失败,还是组件运行后才报错。把链路拆开,排查会快很多。
先确认 remoteEntry 能不能被访问
最基础的问题是 URL 写错、CDN 缓存旧文件、Remote 没发布成功或跨域头缺失。浏览器 Network 里先看 remoteEntry.js 是否 200,再看它加载的 chunk 是否同样成功。很多白屏其实不是 Module Federation 的问题,而是 publicPath 指向了本地或旧 CDN。
jsremotes: { shop: `shop@https://cdn.example.com/shop/remoteEntry.js` }, output: { publicPath: 'auto' }
publicPath: 'auto' 可以解决不少动态 chunk 路径问题,但不是万能药。如果 Remote 产物被放到多层目录,CDN rewrite 规则仍然可能让 chunk 404。
版本冲突要看共享依赖策略
Unsatisfied version、hooks 报错、多个 React 实例共存,通常都和 shared 配置有关。核心框架建议单例,版本范围不要写得太随意。strictVersion 能让问题更早暴露,但也会让灰度发布更容易被版本差异卡住。
jsshared: { react: { singleton: true, requiredVersion: deps.react, strictVersion: false } }
这里的取舍很现实:强约束更安全,弱约束更利于独立发布。对 React、Vue、Angular core 这类依赖,宁可发布前统一版本;对普通工具库,可以允许 Remote 自带一份。
加载失败必须有降级
远程模块天然比本地模块多一段网络链路,所以失败是正常情况,不是异常情况。React 可以用 ErrorBoundary 包住 Suspense,Vue 可以给异步组件配置 errorComponent,Angular 可以在路由加载失败时跳到本地降级页。
jsconst RemotePanel = React.lazy(() => import('shop/Panel').catch(() => import('./FallbackPanel')) )
不要把降级只做成 loading 文案。真正有用的降级要告诉用户哪些功能不可用,同时保证主流程不崩。后台系统至少要让菜单、退出登录和核心页面继续可用。
样式和状态问题要收边界
样式串扰通常来自全局选择器、reset.css、UI 库主题变量或弹层挂载到 body。解决方式不是每次都上 Shadow DOM,而是先统一命名前缀、CSS Modules 和设计 token。状态共享也一样,不要让 Remote 直接读 Host 的完整 store,最好只传必要数据和回调。
追问
remoteEntry 访问正常,组件还是加载失败怎么办?
继续看 remoteEntry 后续请求的 chunk,而不是只盯第一个文件。remoteEntry 只是入口,它里面还会按需加载组件 chunk、样式文件和资源文件。边界在于:入口 200 只能说明容器存在,不能说明暴露的模块路径和 publicPath 都正确。常见坑是 Remote 本地能跑,部署到 CDN 子目录后 chunk 路径仍指向根目录。
strictVersion 应该打开吗?
对核心框架和强耦合运行时可以打开或至少在预发环境打开,让版本问题尽早暴露。对独立性要求高、发布频繁的业务 Remote,生产直接强开可能导致一次小版本差异就整块不可用。取舍是稳定性和发布自由度之间的平衡。我的建议是核心依赖强治理,工具库弱治理,并且在 CI 里提前检查版本差异。
样式污染为什么总是很难排查?
因为污染经常不是当前组件写的,而是 reset、UI 库全局样式、弹层容器或 CSS 加载顺序造成的。它的边界不在 Remote 代码目录,而在整个页面 CSSOM。排查时可以先禁用 Remote 样式文件,再逐个打开确认来源。踩坑点是只改选择器权重,短期看起来好了,下一次加载顺序变化又复发。
多个 Remote 之间怎么共享状态更稳?
优先用 URL、事件、后端接口或 Host 下发的最小上下文,不要让所有 Remote 共享一个大 store。共享 store 看起来省事,但版本升级、权限隔离和回滚都会变难。取舍是短期开发效率和长期边界清晰度。只有登录态、主题、语言这类全局基础状态适合统一管理,复杂业务状态应该留在各自 Remote 内部。
线上如何快速定位是哪一个 Remote 出问题?
加载日志里必须带 remote 名称、remoteEntry URL、版本、chunk URL、耗时和错误类型。只上报“页面白屏”没有排查价值,因为 Host、Remote、CDN 和依赖冲突都会造成白屏。边界是日志不能泄露 token 或用户隐私,只记录技术元信息即可。踩坑最多的是没有版本字段,回滚后也不知道用户到底加载过哪一版。
结论
Module Federation 排障要按链路来:入口文件、chunk 路径、共享依赖、组件运行、样式状态和线上监控。每一层都有自己的边界,不要用一个配置项解决所有问题。能降级、能记录版本、能快速回滚,比追求一次配置永不出错更可靠。