UzumakiItachi
首页
  • JavaSript
  • Vue

    • Vue2
    • Vue3
  • React

    • React_18
  • WebPack
  • 浏览器相关
  • 工程化相关
  • 工作中遇到的问题以及解决方案
  • Git
  • 面试
  • 学习
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 个人产出
  • 实用工具
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

UzumakiItachi

起风了,唯有努力生存。
首页
  • JavaSript
  • Vue

    • Vue2
    • Vue3
  • React

    • React_18
  • WebPack
  • 浏览器相关
  • 工程化相关
  • 工作中遇到的问题以及解决方案
  • Git
  • 面试
  • 学习
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 个人产出
  • 实用工具
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • WebPack

    • WebPack热更新原理
      • 什么是HMR
      • HMR的运转流程
      • hotApply 热更新模块替换
      • 总结
    • 实现一个通用的WebPack配置包
    • WebPack打包多页面应用
    • WebPack构建速度以及体积优化策略
    • 手写一个简易的WebPack
    • 实现一个简易的webpack-loader
    • 实现一个简易的Webpack-plugin
    • 深入WebPack code splitting
    • 实现一个合成雪碧图的loader
    • 实现一个压缩文件的plugin
    • webpack5都升级了哪些东西
    • 实现一个自动收集路由信息的webpack插件
  • 浏览器相关

  • 工程化相关

  • 工作中遇到的问题以及解决方案

  • Git

  • Vite

  • 一些小工具

  • 算法

  • 服务器

  • HTTP

  • 技术
  • WebPack
hanhanbuku
2023-02-28
目录

WebPack热更新原理

# 什么是HMR

HMR即Hot Module Replacement是指当你对代码修改并保存后,webpack将会对代码进行重新打包,并将改动的模块发送到浏览器端,浏览器用新的模块替换掉旧的模块,去实现局部更新页面而非整体刷新页面。 在热更新的过程中有几个重要角色需要提前了解一下,那就是WDS (Webpack-dev-server)和HMR(HotModuleReplacementPlugin)

# HMR的运转流程

看一下我们run dev后webpack到底做了哪些事情 image.png

看流程图已经能看的非常清楚了,本质上其实就是wds在本地通过express去启动了一个web服务器,同时创建了一个webScoket服务 。而HMR则会在bundle里面注入一些热更新相关的代码,其中就包括了客户端连接scoket的代码。这样服务端和客户端就有了一个长连接 webpack会监听文件的变化,每当重新触发了webpack编译后,就会生成一个Hash值,一个json文件,一个js文件(可能没有)

当编译完成后,webpack会通过socket将本次编译后的Hash值发送给客户端,客户端接收到这个值之后会和上一次的Hash做比对 如果一致则走缓存,不一致则发送xxx/hash.hot-update.json的请求,获取热更新的模块以及下次热更新的Hash 随后又会通过jsonP的方式去将本次更新的js文件加载回来。

至于这里为什么要用jsonP呢? 因为jsonP是请求回来的文件是立即执行的,而如果直接将更新后的代码放在scoket中发送的话 还得再做一步代码的处理,所以此处使用jsonP是最方便的。

# hotApply 热更新模块替换

在拿到最新的模块文件之后,要做的就是去替换掉原来老的模块了。 通过hotUpdate可以找到旧模块

var queue = outdatedModules.slice();
while (queue.length > 0) {
    moduleId = queue.pop();
    // 从缓存中删除过期的模块
    module = installedModules[moduleId];
    // 删除过期的依赖
    delete outdatedDependencies[moduleId];
    
    // 存储了被删掉的模块id,便于更新代码
    outdatedSelfAcceptedModules.push({
        module: moduleId
    });
}
1
2
3
4
5
6
7
8
9
10
11
12
13

将新的模块添加到 modules 中

appliedUpdate[moduleId] = hotUpdate[moduleId];
for (moduleId in appliedUpdate) {
    if (Object.prototype.hasOwnProperty.call(appliedUpdate, moduleId)) {
        modules[moduleId] = appliedUpdate[moduleId];
    }
}
1
2
3
4
5
6

通过__webpack_require__执行相关模块的代码

for (i = 0; i < outdatedSelfAcceptedModules.length; i++) {
    var item = outdatedSelfAcceptedModules[i];
    moduleId = item.module;
    try {
        // 执行最新的代码
        __webpack_require__(moduleId);
    } catch (err) {
        // ...容错处理
    }
}
1
2
3
4
5
6
7
8
9
10

# 总结

总结一下就是webpack通过WDS插件启动本地服务器托管静态资源,同时创建scoket服务(HMR 会在bundle里注入runtime,来连接此scoket服务)。然后WDM插件开始监听webpack文件的编译 以便随时通知本地服务器代码变更了。而HMR插件则是在最终打包成的bundle里注入了一系列处理热更新的代码。

webpack每次编译后都会产生一个hash串,并将这个串发送给客户端,客户端就是依据这个串来分别代码是否变更。 如果代码变更了 客户端就会发起一个http请求,去请求一个json文件。json文件里包含了本次更新的模块以及下一次更新所需要的hash值 在做完这些事情之后,HMR会通过jsonP的方式去请求最新的模块资源,然后通过内部的一些手段去进行新老模块的替换

编辑 (opens new window)
上次更新: 2023/02/28, 21:11:57
实现一个通用的WebPack配置包

实现一个通用的WebPack配置包→

最近更新
01
前端检测更新,自动刷新网页
06-09
02
swiper渲染大量数据的优化方案
06-06
03
仿抖音短视频组件实现方案
02-28
更多文章>
Theme by Vdoing | Copyright © 2023-2025 UzumakiItachi | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式