Vite 的热模块替换(HMR)机制基于浏览器原生 ES 模块(ESM)实现,其工作原理如下:
原生 ESM 支持:Vite 利用浏览器对 ESM 的原生支持,在开发环境中直接通过 HTTP 请求加载模块,而不是像 Webpack 那样预先打包所有模块。
WebSocket 通信:Vite 开发服务器与浏览器之间建立 WebSocket 连接,用于实时通信。当源代码文件发生变化时,服务器会通过 WebSocket 通知浏览器。
精确的模块更新:当文件被修改时,Vite 只会重新编译该文件,而不是整个应用。服务器会发送 HMR 更新消息,包含修改的模块路径和更新内容。
浏览器端处理:浏览器接收到 HMR 更新后,通过 import.meta.hot API 接收更新。Vite 在每个模块中注入了 HMR 运行时代码,使得模块能够:
- 接收新的模块导出
- 执行模块的 dispose 函数(如果存在)清理副作用
- 执行模块的 accept 函数处理更新
- 触发依赖该模块的其他模块的更新
级联更新:当一个模块更新时,Vite 会自动更新所有依赖该模块的父模块,确保整个依赖树保持一致。
与 Webpack HMR 的区别:
- Webpack 需要重新打包整个依赖图,HMR 更新需要重新编译多个模块
- Vite 只编译修改的文件,HMR 更新速度与项目规模无关
- Webpack 使用 WebSocket + manifest 文件,Vite 使用 WebSocket + 原生 ESM
性能优势:由于 Vite 的 HMR 不需要重新打包,即使项目包含数千个模块,HMR 更新仍然能在几十毫秒内完成,提供近乎即时的开发体验。