热替换(Hot Module Replacement,简称 HMR)是一种在开发过程中提高开发效率的技术。它允许在应用程序运行时动态替换、添加或删除模块,而无需重新加载整个页面。这可以显著减少从代码更改到效果呈现的时间,提高开发效率。
1. 热替换的优势
- 减少页面刷新:传统的开发模式下,每次代码更改后都需要刷新页面,这会导致状态丢失。HMR 可以在不刷新页面的情况下更新模块,保持应用的状态。
- 快速反馈:开发者可以立即看到代码更改的效果,无需等待页面重新加载。
- 提高开发效率:减少页面刷新的次数,可以显著提高开发效率。
2. 热替换的工作流程
当使用 webpack-dev-server 时,代码改动到效果呈现的过程如下:
- 代码更改:开发者修改代码。
- 重新打包:
webpack-dev-server检测到代码更改,重新打包。 - 页面刷新:默认情况下,
webpack-dev-server会调用location.reload刷新页面。
使用了热替换后,流程发生变化:
- 代码更改:开发者修改代码。
- 重新打包:
webpack-dev-server检测到代码更改,重新打包。 - 热替换:
webpack-dev-server通过 WebSocket 通道将更新的内容发送到浏览器。 - 模块更新:浏览器中的
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 的核心在于在不刷新页面的情况下动态更新模块,保持应用的状态。