当前位置: 首页 > 科技观察

面试官:说说Webpack的热更新是怎么做的?原理是什么?

时间:2023-03-21 16:18:54 科技观察

本文转载自微信公众号《JS日报》,作者慧慧。转载本文请联系JS每日一问公众号。1.什么是HMR?HMR的全称是HotModuleReplacement,可以理解为模块热替换,指的是在应用程序运行过程中更换、添加、删除模块,而不刷新整个应用程序。例如,如果我们在应用程序运行时修改了某个模块,那么整个应用程序将通过自动刷新进行刷新,页面中的状态信息就会丢失。如果使用HMR,只能实时更换修改后的模块。在应用程序中,没有必要完全刷新整个应用程序。在webpack中配置和启用hot模块也很简单,如下代码:constwebpack=require('webpack')module.exports={//...devServer:{//EnabletheHMRfeaturehot:true//hotOnly:true}}通过上面的配置,如果我们修改并保存css文件,确实可以在不刷新的情况下更新到页面。但是当我们修改保存js文件的时候,页面还是自动刷新的,这里并没有触发热模块。因此,HMR不像Webpack的其他功能那样开箱即用。需要一些额外的操作。我们需要指定更新哪些模块以执行HRM。如下代码:if(module.hot){module.hot.accept('./util.js',()=>{console.log("util.jshasbeenupdated")})}二、实现原理首先我们来看一张图,如下:WebpackCompile:将JS源码编译成bundle.jsHMRServer:用于输出热更新文件到HMRRuntimeBundleServer:静态资源文件服务器,提供HMRRuntime的文件访问路径:socketserver,会被注入浏览器,更新文件变化bundle.js:构建输出文件,在HMRRuntime和HMRServer之间建立websocket,即图中第4行,用于更新文件实时变化。上图中可以分为两个阶段:启动阶段就是上面的图1-2-A-B写完还没有被webpack打包的源码后,WebpackCompile将源码和HMRRuntime一起编译成bundle文件,并将其传输到BundleServer。静态资源服务器更新阶段为上图1-2-3-4当某个文件或模块发生变化时,webpack监听文件变化,重新编译打包该文件,编译生成一个唯一的hash值,用作识别下次热更新生成二次修复Ding文件:manifest(包含hash和chundId,用于描述变化的内容)和chunk.js模块由于socket服务器在HMRRuntime和HMRServer之间建立了一个websocket链接,当文件发生变化时,服务器会发送给浏览器浏览器推送一条消息,消息中包含文件更改后生成的哈希值,如下图h属性所示,作为下次热更新的标识。在浏览器接收到这个消息之前,浏览器已经记住了在上一个socket消息中指定hash标识后,此时我们会创建一个ajax请求到服务器去获取变化内容的manifest文件。manifest文件中包含rebuild生成的hash值和变化的module,对应上图中的c属性browser。根据manifest文件获取模块变化的内容,从而触发render进程,实现部分模块更新3.总结webpack模块热更新总结如下:通过webpack-dev-server创建两台服务器:提供静态资源服务(express)和Socket服务express服务器负责直接提供静态资源服务(封装后的资源由浏览器直接请求解析)。socket服务器是websocket长连接,双方可以通信。当socket服务器检测到相应模块发生变化时,会生成两个.json文件(manifestfile)和.js文件(updatechunk),socket服务器可以通过长连接直接发送给客户端(浏览器).浏览器获取到这两个新文件后,会通过HMRRuntime机制,加载这两个文件,并为修改后的模块更新引用https://zhuanlan.zhihu.com/p/138446061https://github.com/Jocs/jocs.github.io/issues/15https://juejin.cn/post/6844904134697549832https://vue3js.cn/interview/