Skip to content

Webpack 热更新是怎么做到的? ​

开发服务器发现文件变了,只把变化的模块推给浏览器,替换旧模块并尽量保留页面状态。做不到安全替换时,再退回整页刷新。

原理 ​

一次编译会多出一份更新清单和若干补丁。浏览器里的运行时先和开发服务器保持连接(常见是 WebSocket)。服务器通知某次编译的哈希,浏览器去拉清单,再按需拉变了的 chunk。

运行时找到旧模块,执行新模块,然后沿着依赖它的模块调用 module.hot.accept。接受了更新的模块自己决定怎么把新导出接到界面上。Vue 和 React 的加载器会替组件写好这段接受逻辑,所以改组件能保住路由和部分状态。

如果链路上没有人接受更新,运行时刷新页面。CSS 常常可以单独换,不必刷新。

热更新依赖开发构建的模块边界。生产包没有这套运行时,改代码必须重新发布。

追问 ​

为什么有时一改就整页刷新?

变的是入口、没人 accept 的文件,或者运行时对不上当前哈希。看终端里是哪一个模块「无法热更新」。不要先关 HMR 来「解决」。

和 Vite 的 HMR 一样吗?

目标一样:换模块、留状态。Vite 利用浏览器的原生模块请求失效,不走 Webpack 那份补丁包。边界情况仍然是「没有人接受这个更新就刷新」。

易错点 ​

  • 以为热更新会合并你正在输入的所有状态。没被框架接住的状态会丢。
  • 在生产配置里打开 HMR 运行时,多一份开发代码。
  • 改了环境变量或 HTML 模板,却期望只换一个函数。

相关 ​