Webpack HMR热更新原理(Hot Module Replacement)
详细解释Webpack HMR(热模块替换)的工作原理,包括Webpack Dev Server、WebSocket通信、模块哈希对比、以及React/Vue中的HMR实现机制。为什么HMR比Live Reload更高效?
回答
我还是少年
HMR核心流程
1. 监听文件变化
- Webpack Dev Server使用chokidar监听文件系统变化
- 检测到文件变更时通知Webpack重新编译
2. 增量编译与Hash
- Webpack增量编译变更模块及其依赖
- 生成:
[hash].hot-update.json(更新清单)+[chunk].hot-update.js(更新代码) - 每个模块编译后生成唯一hash,对比前后hash确定变化
3. WebSocket推送
- WDS通过WebSocket发送更新信息(hash、chunk名)到浏览器
- 浏览器Runtime收到消息后开始更新流程
4. JSONP请求更新
- Runtime构建script标签,请求
[chunk].[hash].hot-update.js - 新的模块代码会执行
module.hot.accept()或module.hot.dispose()
5. 模块替换
HotModuleReplacement.runtime
→ 检查模块的accept handlers
→ 执行旧模块的dispose清理
→ 替换模块缓存
→ 执行新模块代码
→ 标记为过期/
6. 冒泡机制
- 若当前模块未定义accept,向上冒泡到父模块
- 一直冒泡到entry仍未accept → 触发全量刷新(fallback到Live Reload)
React HMR实现
if (module.hot) {
module.hot.accept('./App', () => {
render(<App />, root); // 重新渲染但保留状态
});
}
Vue HMR实现
- Vue Loader内置HMR支持
- .vue文件通过
module.hot.accept替换组件渲染函数 - 保留组件实例状态(data/computed/watch)
HMR vs Live Reload
| 特性 | HMR | Live Reload |
|---|---|---|
| 页面变化 | 不刷新页面 | 全量刷新 |
| 状态保留 | ✅ 保留组件状态 | ❌ 所有状态丢失 |
| 更新速度 | 毫秒级 | 秒级(重载+重编译) |
| 开发体验 | 极佳 | 一般 |
HMR的核心价值在于保持应用状态的同时更新代码,极大提升开发效率。