Webpack的热更新
概念
- Hot Module Replacement,简称HMR,无需完全刷新整个页面的同时,更新模块。HMR的好处,在日常开发工作中体会颇深:节省宝贵的开发时间、提升开发体验
- HMR作为一个Webpack内置的功能,可以通过HotModuleReplacementPlugin或–hot开启
基本思路
- 启动webpack,生成compiler实例。compiler上有很多方法,比如可以启动 webpack 所有编译工作,以及监听本地文件的变化
- 使用express框架启动本地server,让浏览器可以请求本地的静态资源
- 本地server启动之后,再去启动websocket服务。通过websocket,可以建立本地服务和浏览器的双向通信。这样就可以实现当本地文件发生变化,立马告知浏览器可以热更新代码啦
修改webpack.config.js的entry配置
- 启动本地服务前,调用了updateCompiler(this.compiler)方法。这个方法中有 2 段关键性代码。
- 一个是获取websocket客户端代码路径
- 另一个是根据配置获取webpack热更新代码路径
监听webpack编译结束
- 修改好入口配置后,又调用了setupHooks方法。这个方法是用来注册监听事件的,监听每次webpack编译完成
- 当监听到一次webpack编译结束,就会调用_sendStats方法通过websocket给浏览器发送通知,ok和hash事件,这样浏览器就可以拿到最新的hash值了,做检查更新逻辑
webpack监听文件变化
- 每次修改代码,就会触发编译。说明我们还需要监听本地代码的变化,主要是通过setupDevMiddleware方法实现的
- 调用了compiler.watch方法:首先对本地文件代码进行编译打包,也就是webpack的一系列编译流程
- 编译结束后,开启对本地文件的监听,当文件发生变化,重新编译,编译完成之后继续监听
- 执行setFs方法:这个方法主要目的就是将编译后的文件打包到内存中
浏览器接收到热更新的通知
- 我们已经可以监听到文件的变化了,当文件发生变化,就触发重新编译。同时还监听了每次编译结束的事件。当监听到一次webpack编译结束,_sendStats方法就通过websoket给浏览器发送通知,检查下是否需要热更新。下面重点讲的就是_sendStats方法中的ok和hash事件都做了什么
- hash事件,更新最新一次打包后的hash值
- ok事件,进行热更新检查
HotModuleReplacementPlugin
- 如果配置了该插件,就会在Modules里面增加了一个hot属性:hotCreateModule(moduleId);
- hotCreateModule:方法中主要包含:check和apply函数
moudle.hot.check 开始热更新
- 利用上一次保存的hash值,调用hotDownloadManifest发送xxx/hash.hot-update.json的ajax请求
- 请求结果获取热更新模块,以及下次热更新的Hash 标识,并进入热更新准备阶段
- 调用hotDownloadUpdateChunk发送xxx/hash.hot-update.js 请求,通过JSONP方式
- hotAddUpdateChunk方法会把更新的模块moreModules赋值给全局全量hotUpdate
- hotUpdateDownloaded方法会调用hotApply进行代码的替换
hotApply 热更新模块替换
- 删除过期的模块,就是需要替换的模块
- 将新的模块添加到 modules 中
- 通过__webpack_require__执行相关模块的代码