Skip to content

热替换 HMR

热替换并不能降低构建时间(可能还会稍微增加),但可以降低代码改动到效果呈现的时间

当使用webpack-dev-server时,考虑代码改动到效果呈现的过程

|400

而使用了热替换后,流程发生了变化

|400

使用和原理

  1. 更改配置
js
module.exports = {
  devServer: {
    hot: true, // 开启HMR
  },
  plugins: [
    // 可选,要是dev-server开启了hot,此处可以省略
    new webpack.HotModuleReplacementPlugin(),
  ],
};
  1. 更改代码
js
// index.js

if (module.hot) {
  // 是否开启了热更新
  module.hot.accept(); // 接受热更新
}

首先,这段代码会参与最终运行!

当开启了热更新后,webpack-dev-server会向打包结果中注入module.hot属性

默认情况下,webpack-dev-server不管是否开启了热更新,当重新打包后,都会调用location.reload刷新页面

但如果运行了module.hot.accept(),将改变这一行为

module.hot.accept()的作用是让webpack-dev-server通过socket管道,把服务器更新的内容发送到浏览器

|300

然后,将结果交给插件HotModuleReplacementPlugin注入的代码执行

插件HotModuleReplacementPlugin会根据覆盖原始代码,然后让代码重新执行

所以,热替换发生在代码运行期

开启 HMR 就相当于开启了一个 websocket,服务器可以主动的向浏览器发送消息。 当开发者修改代码后,服务器向浏览器发送更新消息,浏览器此时会发送请求,向服务器索要更新的模块,然后 webpack 的 HotModuleReplacementPlugin 就会重新执行更新的模块。 具体的请求可以在开启 HMR 后,浏览器网络中抓包。

样式热替换

对于样式也是可以使用热替换的,但需要使用style-loader

因为热替换发生时,HotModuleReplacementPlugin只会简单的重新运行模块代码

因此style-loader的代码一运行,就会重新设置style元素中的样式

mini-css-extract-plugin,由于它生成文件是在构建期间,运行期间并会也无法改动文件,因此它对于热替换是无效的

MIT License