Open Samgao0312 opened 2 years ago
Webpack的热更新又称热替换(Hot Module Replacement),缩写为HMR。这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。
HMR的核心就是客户端从服务端拉取更新后的文件,准确的说是 chunk diff (chunk 需要更新的部分),实际上 WDS 与浏览器之间维护了一个Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发起Ajax请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该 chunk 的增量更新。
在 Webpack 中配置开启热模块也非常的简单,只需要添加如下代码即可。
const webpack = require('webpack') module.exports = { // ... devServer: { // 开启 HMR 特性 hot: true // hotOnly: true } }
需要说明的是,实现热更新还需要去指定哪些模块发生更新时进行 HRM,因为默认情况下,HRM只对css文件有效。
if(module.hot){ module.hot.accept('./util.js',()=>{ console.log("util.js更新了") }) }
首先,我们来看一张图:
上面图中涉及了很多不同的概念,如下:
整个流程,我们可以将它分为两个阶段:启动阶段 和 更新阶段。
启动阶段: 主要工作是,Webpack Compile 将源代码和 HMR Runtime 一起编译成 bundle 文件,传输给 Bundle Server 静态资源服务器。接下来,我们重点关注下更新阶段:
更新阶段:当某一个文件或者模块发生变化时,webpack 监听到文件变化对文件重新编译打包,编译生成唯一的hash值,这个hash 值用来作为下一次热更新的标识。然后,根据变化的内容生成两个补丁文件:manifest(包含了 hash 和 chundId ,用来说明变化的内容)和 chunk.js 模块。
由于 socket 服务器在 HMR Runtime 和 HMR Server 之间建立 websocket 链接,当文件发生改动的时候,服务端会向浏览器推送一条消息,消息包含文件改动后生成的 hash 值,如下图的 h 属性,作为下一次热更细的标识。
在浏览器接受到这条消息之前,浏览器已经在上一次 socket 消息中已经记住了此时的 hash 标识,这时候我们会创建一个 ajax 去服务端请求获取到变化内容的 manifest 文件。mainfest文件包含重新 build 生成的 hash 值,以及变化的模块,对应上图的 c 属性。浏览器根据 manifest 文件获取模块变化的内容,从而触发 render 流程,实现局部模块更新。
通过前面的分析,总结 Webpack 热模块的步骤如下:
1、什么是热更新
Webpack的热更新又称热替换(Hot Module Replacement),缩写为HMR。这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。
HMR的核心就是客户端从服务端拉取更新后的文件,准确的说是 chunk diff (chunk 需要更新的部分),实际上 WDS 与浏览器之间维护了一个Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发起Ajax请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该 chunk 的增量更新。
在 Webpack 中配置开启热模块也非常的简单,只需要添加如下代码即可。
需要说明的是,实现热更新还需要去指定哪些模块发生更新时进行 HRM,因为默认情况下,HRM只对css文件有效。
2、实现原理
首先,我们来看一张图:![image](https://user-images.githubusercontent.com/18101244/178932315-e4275412-d2f7-405f-9b83-dc061f0e7a49.png)
上面图中涉及了很多不同的概念,如下:
整个流程,我们可以将它分为两个阶段:启动阶段 和 更新阶段。
启动阶段: 主要工作是,Webpack Compile 将源代码和 HMR Runtime 一起编译成 bundle 文件,传输给 Bundle Server 静态资源服务器。接下来,我们重点关注下更新阶段:
更新阶段:当某一个文件或者模块发生变化时,webpack 监听到文件变化对文件重新编译打包,编译生成唯一的hash值,这个hash 值用来作为下一次热更新的标识。然后,根据变化的内容生成两个补丁文件:manifest(包含了 hash 和 chundId ,用来说明变化的内容)和 chunk.js 模块。
由于 socket 服务器在 HMR Runtime 和 HMR Server 之间建立 websocket 链接,当文件发生改动的时候,服务端会向浏览器推送一条消息,消息包含文件改动后生成的 hash 值,如下图的 h 属性,作为下一次热更细的标识。
在浏览器接受到这条消息之前,浏览器已经在上一次 socket 消息中已经记住了此时的 hash 标识,这时候我们会创建一个 ajax 去服务端请求获取到变化内容的 manifest 文件。mainfest文件包含重新 build 生成的 hash 值,以及变化的模块,对应上图的 c 属性。浏览器根据 manifest 文件获取模块变化的内容,从而触发 render 流程,实现局部模块更新。
3、总结
通过前面的分析,总结 Webpack 热模块的步骤如下: