# 用HMR提高开发效率
Hot Module Replacement
,即模块热替换。之前我们使用过Hot Reloading
,当代码变更时通知浏览器刷新页面,避免手动刷新的繁琐环节。
Hot Module Replacement
可以说是Hot Reloading
的增加版,所谓增加,它不用整个页面刷新,而是局部替换掉部分模块代码并且使其生效。
所以,Hot Module Replacement
即避免了频繁手动刷新页面,也减少了页面刷新时的等待时间,以此极大地提高前端页面开发效率
# 配置使用HMR
我们需要在webpack
的配置文件中添加启用HMR
需要的两个插件
const webpack = require('webpack')
module.exports = {
// ...
devServer: {
hot: true // dev-server 的配置要启动 hot,或者在命令行中带参数开启
},
plugins: [
// ...
new webpack.NamedModulesPlugin(), // 用于启动 HMR 时可以显示模块的相对路径
new webpack.HotModuleReplacementPlugin() // Hot Module Replacement 的插件
]
}
2
3
4
5
6
7
8
9
10
11
12
13
# 理解HMR
开启hot
功能的webpack
会往我们应用的主要代码中添加WS
相关的代码,用于和服务连接,等待更新动作
当你配置了HMR
的插件时,会往应用代码中添加HMR
运行时的代码,主要用于定义代码模块应用更新时的API
HMR
运行时代码会提供定义代码模块应用更新执行的API,这些API可以让我们在模块中定义接收到HMR
更新应用信号时,需要额外做一些什么工作
例如,style-loader 就需要实现 HMR 接口,当收到代码更新时,使用新的样式替换旧的样式
if(module.hot){
module.hot.accept('xxx/, () => {
// ...新样式替换旧样式
})
}
2
3
4
5
6
7
HMR
应用更新时是使用webpackHotUpdate
来处理的
webpackHotUpdate(id, {
'modulePath': function() {
// 模块更新后的代码
}
})
2
3
4
5
执行webpackHotUpdate
时如果发现模块代码实现了HMR
接口,就会执行相应的回调或者方法,从而达到应用更新时,模块可以自行管理自己所需要额外做的工作
不过并不是所有的模块都需要做相关的处理,当遇见没有实现HMR
接口的模块是,就会进行冒泡(向上)
# module.hot 常见的 API
# module.hot.accept
module.hot.accept
方法指定在应用特定代码模块更新时执行相应的callback
,第一个参数可以是字符串或者数组
if(module.hot){
module.hot.accept(['./bar.js','./index.css'], () => {
// ... 这样当 bar.js或者 index.css 更新时都会执行该函数
})
}
2
3
4
5
# module.hot.decline
module.hot.decline
对于指定的代码模块,拒绝进行模块代码的更新,进入更新失败状态,例如module.hot.decline('./bar.js')
# module.hot.dispose
module.hot.dispose
用于添加一个处理函数,在当前模块代码被替换时运行该函数
if (module.hot) {
module.hot.dispose((data) => {
// data 用于传递数据,如果有需要传递的数据可以挂在 data 对象上,然后在模块代码更新后可以通过 module.hot.data 来获取
})
}
2
3
4
5
# module.hot.removeDisposeHandler
module.hot.removeDisposeHandler
用于移除dispose
方法添加的callback
module.hot.accept
通常用于指定当前依赖的某个模块更新时需要做的处理,如果是当前模块更新时需要处理的动作,使用 module.hot.dispose
会更加容易方便。