什么是热替换?
热替换(Hot Module Replacement)指的是当我们在开发模式下使用webpack
构建一个项目时,当我们改动项目文件中的代码,不仅webpack要重新构建,并且浏览器也要同步更新页面。所以热替换并不能降低构建的时间,而是降低代码改动到效果呈现的时间。
当使用
webpack-dev-server
时,考虑代码更新到效果呈现的过程
graph TD
代码变动 --> 重新打包 --> 浏览器刷新请求所有资源 --> 浏览器执行代码 -->|监控| 代码变动
使用热替换,流程就发生了改变
graph TD
代码变动 --> 重新打包 --> 浏览器仅请求改变资源 --> 浏览器执行代码 -->|监控| 代码变动
HMR主要做的就算避免每次更改代码导致浏览器重新刷新。
使用和原理
更改配置
module.exports = {
devserver: {
hot: true //开启HMR
},
plugins: [
new webpack.HotModuleReplacementPlugin() //可选
]
}
更改代码
//index.js
if(module.hot){ //是否开启热更新
module.hot.accept() //接受热更新
}
注:上述代码的module是哪里来的呢?我们知道打包后的代码是放在函数 function(module,exports,_webpack_require_){}
中运行的,所以这个module也是该函数提供的
首先上面这段代码会参与最终的运行
当开启了热更新后,webpack-dev-server
会向打包结果中注入module.hot
属性,默认情况下,webpack-dev-server
不管受否开启热更新,当重新打包后,都会调用location.reload
来刷新页面。但是如果运行了modlue.hot.accept()
,则将改变这一行为。
module.hot.accept()
的作用是让服务器把更新的内容发送到浏览器。
然而基于http
协议是做不到服务器主动发送信息给浏览器的,这个时候就需要用到WebSocket
,基于WebSocket
,这样webpack-dev-server
就可以在代码更新后主动将最新的资源发送给浏览器。
graph TD
浏览器 -->|web socket| 服务器 -->|web socket|浏览器
然后再将结果交给插件HotModuleReplacementPlugin
注入的代码执行,插件HotModuleReplacementPlugin
会根据覆盖原始代码,然后让代码重新执行。
所以热替换发生在代码运行期间
样式热替换
对于样式,也是可以使用热替换的,不过需要
使用style-loader
,因为发生热替换时,HotModuleReplacementPlugin
只会简单地重新运行模块代码,因此style-loader
的代码一运行就会重新设置style
元素中的样式。而mini-css-extrat-plugin
,由于它生成文件是在构建期间,运行期间无法改动文件,因此它对于热替换是无效的。