告别页面刷新:Webpack 热替换深度解析 (4)

161 阅读3分钟

热替换(Hot Module Replacement,简称 HMR)是一种在开发过程中提高开发效率的技术。它允许在应用程序运行时动态替换、添加或删除模块,而无需重新加载整个页面。这可以显著减少从代码更改到效果呈现的时间,提高开发效率。

1. 热替换的优势

  • 减少页面刷新:传统的开发模式下,每次代码更改后都需要刷新页面,这会导致状态丢失。HMR 可以在不刷新页面的情况下更新模块,保持应用的状态。
  • 快速反馈:开发者可以立即看到代码更改的效果,无需等待页面重新加载。
  • 提高开发效率:减少页面刷新的次数,可以显著提高开发效率。

2. 热替换的工作流程

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

  1. 代码更改:开发者修改代码。
  2. 重新打包webpack-dev-server 检测到代码更改,重新打包。
  3. 页面刷新:默认情况下,webpack-dev-server 会调用 location.reload 刷新页面。

在这里插入图片描述

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

  1. 代码更改:开发者修改代码。
  2. 重新打包webpack-dev-server 检测到代码更改,重新打包。
  3. 热替换webpack-dev-server 通过 WebSocket 通道将更新的内容发送到浏览器。
  4. 模块更新:浏览器中的 HotModuleReplacementPlugin 注入的代码接收更新内容,覆盖原始代码并重新执行。 在这里插入图片描述

3. 配置热替换

3.1 修改 Webpack 配置

webpack.config.js 中,开启 HMR:

const webpack = require('webpack');

module.exports = {
  devServer: {
    hot: true // 开启 HMR
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin() // 可选
  ],
  // 其他配置...
};
3.2 修改代码

在需要热替换的模块中,添加 HMR 代码:

// 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 通过 WebSocket 通道将服务器更新的内容发送到浏览器 在这里插入图片描述 然后,将结果交给插件HotModuleReplacementPlugin注入的代码执行

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

4. 样式热替换

对于样式文件,也可以使用热替换,但需要使用 style-loader。因为热替换发生时,HotModuleReplacementPlugin 只会简单地重新运行模块代码,style-loader 的代码一运行,就会重新设置 style 元素中的样式。

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  // 其他配置...
};

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

5. 总结

通过配置 HMR,可以显著提高开发效率,减少从代码更改到效果呈现的时间。HMR 的核心在于在不刷新页面的情况下动态更新模块,保持应用的状态。