Nx React模块联邦开启HMR后主机项目热重载失效问题
问题原因
- Nx 16.x及更早版本的
@nrwl/react:module-federation-dev-server执行器存在代理逻辑缺陷:主机应用启动时会默认将所有路径(包括HMR依赖的Websocket连接)的请求代理到配置的远程应用服务,主机自身的代码变更事件无法通过Websocket推送到浏览器端,因此主机侧HMR失效;远程应用单独监听自身端口,无代理干扰,因此HMR可正常工作。 - 配置合并逻辑异常:当前主机配置的
hmr: true写在顶层options块,development配置块未显式声明hmr开关,部分Nx版本下development块的默认hmr=false配置会覆盖顶层配置,导致主机实际未启用HMR,仅开启了基础文件监听。 - 共享依赖配置问题:若主机侧React相关依赖未设置
eager: true,React Refresh的热更新边界会被模块联邦的异步加载逻辑破坏,即使HMR连接正常也无法完成模块替换。
修复方案
按照以下步骤逐一调整配置即可:
- 修正主机应用
project.json的serve配置,将hmr开关显式写入development配置块,关闭冲突的liveReload(liveReload为整页刷新逻辑,与HMR同时启用时会抢占Websocket连接):
"serve": { "executor": "@nrwl/react:module-federation-dev-server", "defaultConfiguration": "development", "options": { "buildTarget": "client:build", "port": 4200 }, "configurations": { "development": { "buildTarget": "client:build:development", "open": true, "watch": true, "hmr": true, "liveReload": false, "hot": "only" }, "production": { "buildTarget": "client:build:production", "hmr": false } } }
- 调整主机侧模块联邦共享配置,给React核心依赖开启eager加载,修复热更新边界失效问题:
// 主机目录下的module-federation.config.js const { withModuleFederation } = require('@nrwl/react/module-federation'); const baseConfig = require('./module-federation.config'); module.exports = withModuleFederation({ ...baseConfig, remotes: ['assets'], // 保持原有远程应用配置即可,不要硬编码代理端口 shared: (depName, sharedConfig) => { if (['react', 'react-dom', 'react/jsx-dev-runtime'].includes(depName)) { return { ...sharedConfig, eager: true, requiredVersion: sharedConfig.requiredVersion } } return sharedConfig; } });
- 若调整后仍存在HMR连接被代理到远程端口的问题,在主机的自定义webpack配置中添加代理排除规则,将HMR专用的
/ws路径留在主机本地服务处理:
// 主机目录下的webpack.config.js module.exports = { devServer: { proxy: { '!/ws': { target: 'http://localhost:4201', ws: true } } } }
- 清除缓存重启服务:
- 先执行
nx reset清除Nx构建与devServer缓存 - 分两个独立终端窗口依次启动服务,不要使用
nx run-many批量启动(批量启动模式下部分版本会丢失devServer上下文配置):- 第一个终端执行
nx serve assets启动远程应用 - 第二个终端执行
nx serve client启动主机应用
- 第一个终端执行
- 先执行
调整完成后修改主机侧代码即可正常触发热更新,不会触发无意义的整页刷新。
内容的提问来源于stack exchange,提问作者Nir Berko
相关产品推荐
相关产品推荐

