HMR热更新原理

原文链接:https://zhuanlan.zhihu.com/p/30669007

先贴个图复习一下HMR的流程,这里是使用webpack的插件webpack-dev-server来实现,还可以通过node与webpack-hot-middleware、webpack-dev-middleware来实现,可以参考:https://zhuanlan.zhihu.com/p/30623057

整个理解可以为:

  1. 当改变模块代码(某个js文件)时,服务端webapck-dev-server的中间件webpack-dev-middleware会调用服务端的webapck暴露在全局中的api,会用wacth监控文件的改变,然后将信息传递给服务端的webpack , 服务端的webapk将重新打包。

  2. 服务端的webpack打包时,会把打包好的文件输出到内存中,也就是将文件输出系统(outputFileSystem)变成内存输出系统(MemoryFileSystem),在内存里找文件更快,也避免了代码写入文件的开销。

  3. wetbapk-dev-middleware通过websocket与webapck-dev-server客户端建立连接,(可能会懵逼,webapck-dev-server不是开启服务的,属于服务端的吗?我的理解是,webapck-dev-servert它包含了客户端和服务端的,分别存在浏览器端【开发工具里的source应用里】和服务器端【在开启服务器时用到】),也就是webapck-dev-middleware 把服务端的webpack的打包信息(hash值,compile的done事件【打包结束】)通过websoket发给webpack-dev-server/client(客户端).

  4. webapck-dev-server/client 接收到消息后并不会请求变化的模块的代码,也不会执行模块的更新。会先保存hash值,判断返回消息为ok,把消息传给客户端的webpack, webapck在根据热更新配置,没有配置就刷新页面。有就把执行客户端webapck方法。

  5. 客户端webapck主要通过三个模块的配合来实现模块的替换,当监听到客户端的webpack-dev-server传递的消息时,客户端的webpack会调用webpack/lib/HotModuleReplacement.runtime(简称 HMR runtime)的check方法检查是否有新的更新。在check的过程中,主要调用两个方法,hotDownLoadUpdateChunk【用jsonp的方法xi向后台请求新的模块代码】和hotDowbloadmanifest【ajax向后台请求文件列表消息,有就返回到浏览器】,chunk过程将会返回请求到的模块代码和文件更新的消息到 HMR runtime ,HMRruntime会根据这些返回的消息来决定是刷新页面还是替换模块。

  6. HNR runtime 用得到的新模块替换旧的模快。首先找到旧的模块[outdatedModules]和 旧的模块依赖【outdatedDependencies】,从内存中删除,将新的模块添加到 modules 中,当调用 __webpack_require__ (webpack 重写的 require 方法)方法的时候,就是获取到了新的模块代码了。

  7. 然而我们的业务代码(自己写的代码),不知道模块发生了变化(新的替换了旧的),所以得在业务代码里添加模块更新后的函数。也就是是有module.hot.accept(),方法。

Last updated