当前位置: 首页 > article >正文

Webpack 热更新(HMR)详解:原理与实现

什么是 HMR

HMR(Hot Module Replacement)全称模块热替换,是指在应用程序运行过程中,替换、添加或删除模块,而无需重新刷新整个应用。例如,我们在应用运行过程中修改了某个模块,如果不使用 HMR,自动刷新会导致整个应用的整体刷新,从而导致页面中的状态信息丢失。而使用 HMR,可以实现只将修改的模块实时替换到应用中,不必完全刷新整个应用。

在 Webpack 中配置开启热模块也非常简单,如下代码所示:

const webpack = require('webpack');

module.exports = {
  devServer: {
    // 开启 HMR 特性
    hot: true,
    // hotOnly: true // 仅在支持 HMR 的浏览器中启用 HMR
  }
};

通过上述配置,如果我们修改并保存 CSS 文件,确实能够以不刷新的形式更新到页面中。然而,当我们修改并保存 JS 文件之后,页面依旧会自动刷新。这是因为 HMR 并不像 Webpack 的其他特性一样可以开箱即用,需要一些额外的操作。我们需要指定哪些模块发生更新时进行 HMR,如下代码所示:

if (module.hot) {
  module.hot.accept('./util.js', () => {
    console.log('util.js 更新了');
  });
}

实现原理

Webpack 编译过程
  1. Webpack Compile: 将 JavaScript 源代码编译成 bundle.js
  2. HMR Server: 用来将热更新的文件输出给 HMR Runtime。
  3. Bundle Server: 静态资源文件服务器,提供文件访问路径。
  4. HMR Runtime: 一个 Socket 服务器,会被注入到浏览器中,用于监听文件的变化。
  5. bundle.js: 构建输出的文件。
HMR 运行机制
  1. 启动阶段

    • 编写未经过 Webpack 打包的源代码。
    • Webpack 编译将源代码和 HMR Runtime 一起编译成 bundle.js 文件。
    • bundle.js 文件被传输给 Bundle Server 静态资源服务器。
  2. 更新阶段

    • 当某个文件或模块发生变化时,Webpack 监听到文件变化并重新编译打包。
    • 编译生成唯一的 hash 值,这个 hash 值作为下一次热更新的标识。
    • 根据变化的内容生成两个补丁文件:manifest.json(包含 hash 和 chunkId,说明变化的内容)和 chunk.js(变化的模块)。
    • 由于 Socket 服务器在 HMR Runtime 和 HMR Server 之间建立了 WebSocket 链接,当文件发生改动时,服务端会向浏览器推送一条消息,消息包含文件改动后生成的 hash 值。
    • 浏览器接收到这条消息后,会创建一个 AJAX 请求去服务端获取变化内容的 manifest.json 文件。
    • manifest.json 文件包含重新 build 生成的 hash 值以及变化的模块。
    • 浏览器根据 manifest.json 文件获取模块变化的内容,从而触发 render 流程,实现局部模块更新。

总结

关于 Webpack 热模块更新的总结如下:

  • 通过 webpack-dev-server 创建两个服务器
    • Express Server:负责提供静态资源的服务(打包后的资源直接被浏览器请求和解析)。
    • Socket Server:是一个 WebSocket 的长连接,双方可以通信。
  • 当 Socket Server 监听到对应的模块发生变化时,会生成两个文件:manifest.json(包含 hash 和 chunkId)和 chunk.js(变化的模块)。
  • 通过长连接,Socket Server 可以直接将这两个文件主动发送给客户端(浏览器)。
  • 浏览器拿到两个新的文件后,通过 HMR runtime 机制,加载这两个文件,并且针对修改的模块进行更新。

通过 HMR,开发者可以在不丢失应用状态的情况下,实时看到代码更改的效果,从而提高开发效率。


http://www.kler.cn/a/407241.html

相关文章:

  • [代码随想录Day21打卡] 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树 总结篇
  • 10-单表查询
  • UVM 验证方法学之interface学习系列文章(七)高级 《bind 操作》(4)级联
  • Python Selenium:Web自动化测试与爬虫开发
  • GitLab使用操作v1.0
  • CSS布局学习1
  • 学习嵩山版《Java 开发手册》:编程规约 - 命名风格(P1 ~ P2)
  • 如何进行Apache的配置与调试?
  • Centos环境安装Docker
  • 谈谈法律专业留学dissertation的写作原则与要求
  • 基于Java Springboot高校奖助学金系统
  • el-table表格展示和传值分隔写法
  • SpringCloud Gateway转发请求到同一个服务的不同端口
  • 大模型(LLMs)增量预训练篇
  • Rust 智能指针
  • AI大模型开发架构设计(19)——大模型向量数据库企业级应用实践
  • 插排快排
  • Leetcode169. 多数元素(HOT100)
  • Apple Vision Pro开发002-新建项目配置
  • Python的3D可视化库 - vedo (2)visual子模块 基本可视化行为
  • vue3+echarts+ant design vue实现进度环形图
  • uniapp input限制输入负数,以及保留小数点两位.
  • 【接口封装】——2、鼠标移动窗体
  • Python网络爬虫实践案例:爬取猫眼电影Top100
  • ssm150旅游网站的设计与实现+jsp(论文+源码)_kaic
  • 大数据调度组件之Apache DolphinScheduler