logo
  • 指南
  • 配置
  • 插件
  • API
  • 示例
  • 社区
  • Modern.js 2.x 文档
  • 简体中文
    • 简体中文
    • English
    • 开始
      介绍
      快速上手
      版本升级
      名词解释
      技术栈
      核心概念
      页面入口
      构建工具
      Web 服务器
      基础功能
      路由
      路由基础
      配置式路由
      数据管理
      数据获取
      数据写入
      数据缓存
      渲染
      服务端渲染(SSR)
      服务端流式渲染(Streaming SSR)
      渲染缓存
      静态站点生成(SSG)
      渲染预处理 (Render Preprocessing)
      样式开发
      引入 CSS
      使用 CSS Modules
      使用 CSS-in-JS
      使用 Tailwind CSS
      HTML 模板
      引用静态资源
      引用 JSON 文件
      引用 SVG 资源
      引用 Wasm 资源
      调试
      数据模拟(Mock)
      网络代理
      使用 Rsdoctor
      使用 Storybook
      测试
      Playwright
      Vitest
      Jest
      Cypress
      路径别名
      环境变量
      构建产物目录
      部署应用
      进阶功能
      使用 Rspack
      使用 BFF
      基础用法
      运行时框架
      扩展 BFF Server
      扩展一体化调用 SDK
      文件上传
      跨项目调用
      优化页面性能
      代码分割
      静态资源内联
      产物体积优化
      React Compiler
      提升构建性能
      浏览器兼容性
      配置底层工具
      源码构建模式
      服务端监控
      Monitors
      日志事件
      指标事件
      国际化
      基础概念
      快速开始
      配置说明
      语言检测
      资源加载
      路由集成
      API 参考
      高级用法
      最佳实践
      自定义 Web Server
      专题详解
      模块联邦
      简介
      开始使用
      应用级别模块
      服务端渲染
      部署
      集成国际化能力
      常见问题
      依赖安装问题
      命令行问题
      构建相关问题
      热更新问题
      已下线功能
      📝 编辑此页面
      上一页构建相关问题下一页已下线功能

      #热更新问题

      #热更新不生效,如何排查?

      热更新不生效有很多种可能的原因,在这篇文档中会介绍大部分常见的原因,你可以参照以下内容进行排查。

      在开始排查之前,请简单了解一下热更新的原理:

      热更新原理
      1. 浏览器和开发服务器建立一个 Web Socket 连接,用于实时通信。
      2. 当开发服务器每次重新编译完成后,会通过 Web Socket 通知浏览器,浏览器向开发服务器发送 hot-update.xxx 请求,从而加载编译后的新模块。
      3. 当浏览器收到新的模块后,如果是 React 项目,则会通过 React 官方的 React Refresh 来更新 React 组件,其他框架也是类似。

      了解完热更新的原理后,你可以按照以下步骤来进行基本的排查:

      #1. 检查 Web Socket 连接

      打开浏览器的控制台,查看是否有 [HMR] connected. 日志。

      • 如果有,说明 Web Socket 连接正常,请继续检查后续步骤。
      • 如果没有,请打开 Chrome 的 Network 面板,查看 ws://[host]:[port]/webpack-hmr 的请求状态,若请求异常,说明热更新失败的原因是 Web Socket 请求没有建立成功。

      Web Socket 请求没有建立成功的原因可能有很多种,例如开启了网络代理,导致 Web Socket 请求没有正确发送到开发服务器。你可以检查 Web Socket 请求的地址是否为你的开发服务器地址,如果不是,则可以通过 tools.devServer.client 来配置 Web Socket 请求的地址。

      #2. 检查 hot-update 请求

      当你修改一个模块的代码,并触发重新编译后,浏览器会向开发服务器发送若干个 hot-update.json 和 hot-update.js 请求,用于获取更新后的代码。

      你可以尝试修改一个模块并检查 hot-update.xxx 请求的内容,如果请求的内容是最新的代码,说明热更新的请求正常。

      如果请求的内容错误,大概率也是由于开启了网络代理,请检查 hot-update.xxx 请求的地址是否为你的开发服务器地址,如果不是,则需要调整代理规则,将 hot-update.xxx 请求代理到开发服务器地址。

      #3. 检查其他原因

      如果以上两个步骤都没有问题,那么可能是其他原因导致的热更新失败,比如没有符合 React 对热更新的要求,你可以参考下列的问题进行排查。


      #打包时 external React 后,热更新不生效?

      为了保证热更新生效,我们需要使用 React 和 ReactDOM 的开发环境产物。

      当你将 React 通过 externals 排除后,通常会通过 CDN 等方式注入 React 的生产环境产物,所以热更新会不生效。

      export default {
        output: {
          externals: {
            react: 'React',
            'react-dom': 'ReactDOM',
          },
        },
      };

      为了解决该问题,你需要引用 React 的开发环境产物,或者在开发环境下不配置 externals。

      如果你不确定当前使用的 React 产物类型,可以参考:React 官方文档 - Use the Production Build


      #开发环境设置文件名的 hash 后,热更新不生效?

      通常来说,我们只会在生产环境下设置文件名的 hash 值(即 process.env.NODE_ENV === 'production' 时)。

      如果你在开发环境下设置了文件名的 hash,那么可能会导致热更新不生效(尤其是 CSS 文件)。这是因为每次文件内容变化时,都会引起 hash 变化,导致 mini-css-extract-plugin 等工具无法读取到最新的文件内容。

      • 正确用法:
      export default {
        output: {
          filename: {
            css:
              process.env.NODE_ENV === 'production'
                ? '[name].[contenthash:8].css'
                : '[name].css',
          },
        },
      };
      • 错误用法:
      export default {
        output: {
          filename: {
            css: '[name].[contenthash:8].css',
          },
        },
      };

      #React 组件的热更新无法生效?

      Modern.js 使用 React 官方的 Fast Refresh 能力来进行组件热更新。

      如果出现 React 组件的热更新无法生效的问题,或者是热更新后 React 组件的 state 丢失,这通常是因为你的 React 组件使用了匿名函数。在 React Fast Refresh 的官方实践中,要求组件不能为匿名函数,否则热更新后无法保留 React 组件的 state。

      以下是一些错误用法的例子:

      // 错误写法 1
      export default function () {
        return <div>Hello World</div>;
      }
      
      // 错误写法 2
      export default () => <div>Hello World</div>;

      正确用法是给每个组件函数声明一个名称:

      // 正确写法 1
      export default function MyComponent() {
        return <div>Hello World</div>;
      }
      
      // 正确写法 2
      const MyComponent = () => <div>Hello World</div>;
      
      export default MyComponent;

      #开启 https 后,热更新不生效?

      当开启 https 时,由于证书的问题,可能会出现 HMR 连接失败的情况,此时打开控制台,会出现 HMR connect failed 的报错。

      hmr-connect-error-0

      此问题的解决方法为:点击 Chrome 浏览器问题页面的「高级」->「继续前往 xxx(不安全)」。

      hmr-connect-error-1

      Tips: 当通过 Localhost 访问页面时,「您的连接不是私密连接」字样可能不会出现,可访问 Network 域名进行处理。