HMR -Hot Module Repalce

HMR- Hot Module Replacement

使用前提:项目必须是基于webpack-dev-server或webpac-dev-middle
使用方式, 如下
const webpack = require('webpack');
module.exports = {
    // ...
    plugins: [
        new webpack.HotModuleReplacementPlugin();
    ],
    devServer: {
        hot: true
    }
}
上面的配置的结果会为每个模块绑定一个module.hot对象,这个对象包含的HMR的API,借助这些API我们不仅可以实现对特定模块的开启或关闭HMR,也可以添加热替换额外的逻辑。
在每个模块内调用API的方式有两种:
  • 手动在每个模块内添加
  • 借助一些第三方工具:react-hot-loader、vue-loader
// 手动在index.js中添加
if(module.hot){
    module.hot.replace()
}

HMR原理

在本地开发环境下,浏览器时客户端,webpack-dev-server(WDS)相当于服务端。HMR的核心就是客户端从服务端拉取更新的资源(准确的说是chunk diff)

HMR流程

上面提到客户端会向服务端拉取更新的资源,那么什么时候拉取就成了首要问题

一、确定拉取时间

WDS实际上与浏览器之间维护了一个websocket实时监听本地源文件,当本地资源发生了变化WDS向浏览器推送更新事件,并带上这次构建的hash,让客户端有上一次资源进行对比。

通过hash的比对可以防止冗余更新,因为有些时候的源文件的更改并不一定代表构建结果的更改(比如添加了一个文件末尾空行)

websocket发送事件列表如图,可以看出每个事件的数据正是上面说到的hash
HMR -Hot Module Repalce_第1张图片

二、确定拉取内容
客户端通过hash对比知道了新的构建资源和本地源文件有了差别,那么就会向WDS发送一个请求来获取更改文件的列表。通常这个请求的名字为[hash].hot-update.json。
浏览器请求

HMR -Hot Module Repalce_第2张图片

WDS响应

HMR -Hot Module Repalce_第3张图片

返回字段h代表更新后的hash,c代表chunk;这样客户端已经知道需要拉取的chunkName和hash了,然后继续向WDS发送请求获取该chunk的增量更新((具体更新资源)。请求为[chunkName].[hash].hot-update.js
请求

HMR -Hot Module Repalce_第4张图片

响应

HMR -Hot Module Repalce_第5张图片

这就是HMR的整个过程,至于客户端获取到这些增量更新之后如何处理?那些状态保留,哪需要更新就不是webpack的工作了,此时我们可以利用Webpack的API(module.hot.accept等)对每个模块的自身场景进行处理。像react-hot-loader和vue-loader都是借助这些API来实现HMR的。

你可能感兴趣的:(webpack)