前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >webpack 热更新(HMR)实现原理

webpack 热更新(HMR)实现原理

原创
作者头像
伯爵
修改2020-04-28 10:26:09
3.1K0
修改2020-04-28 10:26:09
举报
文章被收录于专栏:前端小菜鸟前端小菜鸟

HMR(Hot Module Replacement)是webpack一个重要的特性,当代码文件修改并保存之后,webapck通过watch监听到文件发生变化,会对代码文件重新打包生成两个模块补丁文件manifest(js)和一个(或多个)updated chunk(js),将结果存储在内存文件系统中,通过websocket通信机制将重新打包的模块发送到浏览器端,浏览器动态的获取新的模块补丁替换旧的模块,浏览器不需要刷新页面就可以实现应用的更新。

优点:

  • 代码文件修改到页面内容更新,自动完成
  • 兼容目前市面上主流的开发框架 :react,vue,angular2,如使用angular-cli创建ng项目通过@ngtools/webpack已经内置了webpack
  • 相比location.reload() 更新方式,不需要刷新页面,可以保存应用的当前状态

HMR相关的中间件

  • webpack-dev-middleware

本质上是一个容器,将webpack处理后的文件传递个服务器。

webpack-dev-middleware 是一个 express 中间件,核心实现两个功能:第一通过file-loader内部集成了node的 monery-fs/memfs 内部文件系统,,直接将资源存储在内存;第二是通过watch监听文件的变化,动态编译。

  • webpack-hot-middleware

核心是给webpack提高服务端和客户端之间的通信机制,内部使用windoe.EventSocurce实现。

在webpack第一次打包的时候,除了代码本身之外,还包含一部分HMRruntime订阅服务代码,HMRruntime 订阅服务端的更新变化,触发HMR runtime API拉取最新的资源模块。

webpack-hot-middleware实现页面的热重载。

  • webpack-dev-server

内置了webpack-dev-middleware和express服务器,利用webpack-dev-middleware提供文件的监听和编译,利用express提供http服务,底层利用websocket代替EventSource实现了webpack-hot-middleware提供的客户端和服务器之间的通信机制。

HMR的工作原理

图片
图片
  1. webpack --watch启动监听模式之后,webpack第一次编译项目,并将结果存储在内存文件系统,相比较磁盘文件读写方式内存文件管理速度更快,内存webpack服务器通知浏览器加载资源,浏览器获取的静态资源除了JS code内容之外,还有一部分通过webpack-dev-server注入的的 HMR runtime代码,作为浏览器和webpack服务器通信的客户端(webpack-hot-middleware 提供类似的功能)。截图如下:
image
image

2. 文件系统中一个文件(或者模块)发生变化,webpack监听到文件变化对文件重新编译打包,每次编译生成唯一的hash值,根据变化的内容生成两个补丁文件:说明变化内容的manifest(文件格式是hash.hot-update.json,包含了hash和chundId用来说明变化的内容)和chunk js(hash.hot-update.js)模块。

image
image

3. hrm-server通过websocket将manifest推送给浏览器

浏览器接受到最新的hotCurrentHash,触发 hotDownloadManifest函数,获取manifest json 文件。

代码语言:txt
复制
function hotDownloadManifest() {
    var request = new XMLHttpRequest();
    var requestPath = __webpack_require__.p + "" + hotCurrentHash + ".hot-update.json";
    request.open("GET", requestPath, true);		
    request.send(null);
}
image
image

4. 浏览器端hmr runtime根据manifest的hash和chunkId使用ajax拉取最新的更新模块chunk

代码语言:javascript
复制
function hotDownloadUpdateChunk(chunkId) {     
    var script = document.createElement("script");     
    script.src = __webpack_require__.p + ""                       
               + chunkId + "." + hotCurrentHash + ".hot-update.js";	     
    document.head.appendChild(script); 
}
image
image

4. 触发render流程实现局部热重载 HMR runtime 调用window"webpackHotUpdate" 方法,调用hotAddUpdateChunk

代码语言:javascript
复制
var parentHotUpdateCallback = window["webpackHotUpdate"];
window["webpackHotUpdate"] = function webpackHotUpdateCallback(chunkId, moreModules) {
    hotAddUpdateChunk(chunkId, moreModules);
    if (parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules);
};

hotAddUpdateChunk动态的更新代码模块,并调用hotUpdateDownloaded函数

代码语言:javascript
复制
function hotAddUpdateChunk(chunkId, moreModules) {
    hotRequestedFilesMap[chunkId] = false;
    for (var moduleId in moreModules) {
        if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
            hotUpdate[moduleId] = moreModules[moduleId]; 			}
    }
    if (--hotWaitingFiles === 0 && hotChunksLoading === 0) {
        hotUpdateDownloaded();
    }
}

hotUpdateDownloaded执行hotApply执行热重载

代码语言:javascript
复制
function hotUpdateDownloaded() {
    hotSetStatus("ready");
    Promise.resolve()
        .then(function() {
            return hotApply(hotApplyOnUpdate);
        })
}

参考

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 优点:
  • HMR相关的中间件
  • HMR的工作原理
  • 参考
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档