說說webpack的熱更新是如何做到的?原理是什麼?

来源:https://www.cnblogs.com/smileZAZ/p/18211562
-Advertisement-
Play Games

一、是什麼 HMR全稱 Hot Module Replacement,可以理解為模塊熱替換,指在應用程式運行過程中,替換、添加、刪除模塊,而無需重新刷新整個應用 例如,我們在應用運行過程中修改了某個模塊,通過自動刷新會導致整個應用的整體刷新,那頁面中的狀態信息都會丟失 如果使用的是 HMR,就可以實 ...


一、是什麼

HMR全稱 Hot Module Replacement,可以理解為模塊熱替換,指在應用程式運行過程中,替換、添加、刪除模塊,而無需重新刷新整個應用

例如,我們在應用運行過程中修改了某個模塊,通過自動刷新會導致整個應用的整體刷新,那頁面中的狀態信息都會丟失

如果使用的是 HMR,就可以實現只將修改的模塊實時替換至應用中,不必完全刷新整個應用

webpack中配置開啟熱模塊也非常的簡單,如下代碼:

const webpack = require('webpack')
module.exports = {
  // ...
  devServer: {
    // 開啟 HMR 特性
    hot: true
    // hotOnly: true
  }
}

通過上述這種配置,如果我們修改並保存css文件,確實能夠以不刷新的形式更新到頁面中

但是,當我們修改並保存js文件之後,頁面依舊自動刷新了,這裡並沒有觸發熱模塊

所以,HMR並不像 Webpack 的其他特性一樣可以開箱即用,需要有一些額外的操作

我們需要去指定哪些模塊發生更新時進行HRM,如下代碼:

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

二、實現原理

首先來看看一張圖,如下:

  • Webpack Compile:將 JS 源代碼編譯成 bundle.js
  • HMR Server:用來將熱更新的文件輸出給 HMR Runtime
  • Bundle Server:靜態資源文件伺服器,提供文件訪問路徑
  • HMR Runtime:socket伺服器,會被註入到瀏覽器,更新文件的變化
  • bundle.js:構建輸出的文件
  • 在HMR Runtime 和 HMR Server之間建立 websocket,即圖上4號線,用於實時更新文件變化

上面圖中,可以分成兩個階段:

  • 啟動階段為上圖 1 - 2 - A - B

在編寫未經過webpack打包的源代碼後,Webpack Compile 將源代碼和 HMR Runtime 一起編譯成 bundle文件,傳輸給Bundle Server 靜態資源伺服器

  • 更新階段為上圖 1 - 2 - 3 - 4

當某一個文件或者模塊發生變化時,webpack監聽到文件變化對文件重新編譯打包,編譯生成唯一的hash值,這個hash值用來作為下一次熱更新的標識

根據變化的內容生成兩個補丁文件:manifest(包含了 hash 和 chundId,用來說明變化的內容)和chunk.js 模塊

由於socket伺服器在HMR Runtime 和 HMR Server之間建立 websocket鏈接,當文件發生改動的時候,服務端會向瀏覽器推送一條消息,消息包含文件改動後生成的hash值,如下圖的h屬性,作為下一次熱更細的標識

 

在瀏覽器接受到這條消息之前,瀏覽器已經在上一次socket 消息中已經記住了此時的hash 標識,這時候我們會創建一個 ajax 去服務端請求獲取到變化內容的 manifest 文件

mainfest文件包含重新build生成的hash值,以及變化的模塊,對應上圖的c屬性

瀏覽器根據 manifest 文件獲取模塊變化的內容,從而觸發render流程,實現局部模塊更新

三、總結

關於webpack熱模塊更新的總結如下:

  • 通過webpack-dev-server創建兩個伺服器:提供靜態資源的服務(express)和Socket服務
  • express server 負責直接提供靜態資源的服務(打包後的資源直接被瀏覽器請求和解析)
  • socket server 是一個 websocket 的長連接,雙方可以通信
  • 當 socket server 監聽到對應的模塊發生變化時,會生成兩個文件.json(manifest文件)和.js文件(update chunk)
  • 通過長連接,socket server 可以直接將這兩個文件主動發送給客戶端(瀏覽器)
  • 瀏覽器拿到兩個新的文件後,通過HMR runtime機制,載入這兩個文件,並且針對修改的模塊進行更新

參考文獻

  • https://zhuanlan.zhihu.com/p/138446061
  • https://github.com/Jocs/jocs.github.io/issues/15
  • https://juejin.cn/post/6844904134697549832
  • https://vue3js.cn/interview/

如果對您有所幫助,歡迎您點個關註,我會定時更新技術文檔,大家一起討論學習,一起進步。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 事情是這樣的,因為系統漏洞問題,需要升級openssh,從OpenSSH_9.3p1升級到OpenSSH_9.3p2 系統版本:CentOS 7 升級OpenSSH_9.3p2之前需要先升級zlib 從官網下載 wget https://www.zlib.net/zlib-1.3.1.tar.gz ...
  • Linux不像windows系統那樣方便的圖形界面,特別是作為伺服器使用的時候,只有命令行可以使用。 我有個雲伺服器平時用來做一些數據分享用的,最近想看看磁碟和其中文件的占用情況,於是搜索並學習了一些查看磁碟空間信息的命令,命令雖然簡單,但對我自己來說還是有些新的東西值得記錄。 1. df 首先,登 ...
  • Centos7安裝weblogic 1、配置java環境weblogic運行依賴java環境,所以第一步先配置java環境上傳、解壓jdk安裝包[root@bogon ~]# rz -be[root@bogon ~]# tar -zxvf jdk1.8.tar.gz 配置java環境變數[root@ ...
  • 背景 根據orangepi zero2用戶手冊說明,linux5.13內核不能使用 modprobe fbtft_device 驅動spi lcd 查看linux內核源碼提交記錄,發現在v5.4-rc3中刪除了fbtft_device.c文件 commit如下 staging/fbtft: Remo ...
  • 一、卸載mariadb的rpm包 1、首先,你需要找出已安裝的MariaDB包的具體名稱。可以使用以下命令列出所有已安裝的MariaDB包: rpm -qa | grep mariadb 2、刪除命令(安裝mysql不一定需要卸載)yum -y remove +【上圖的文件名】或者rpm -e -- ...
  • 前言 應用中的信息傳遞是為了實現各種功能和交互。信息傳遞可以幫助用戶和應用之間進行有效的溝通和交流。通過信息傳遞,應用可以向用戶傳遞重要的消息、通知和提示,以提供及時的反饋和指導。同時,用戶也可以通過信息傳遞嚮應用發送指令、請求和反饋,以實現個性化的需求和操作。 信息傳遞還可以幫助應用之間實現數 ...
  • Symbol 引用 iconfont icon圖標庫 Symbol 引用 這是一種全新的使用方式,應該說這才是未來的主流,也是平臺目前推薦的用法。相關介紹可以參考這篇文章 這種用法其實是做了一個 SVG 的集合,與另外兩種相比具有如下特點: 支持多色圖標了,不再受單色限制。 通過一些技巧,支持像字體 ...
  • XML中的字元串數據類型表示字元序列,包括換行、回車和製表符。處理器不修改值。`normalizedString`去除這些特殊字元,`token`則進一步移除前導和尾隨空格及多餘空格。字元串類型可使用枚舉、長度等限制。`date`和`dateTime`數據類型表示日期和時間,`duration`表示... ...
一周排行
    -Advertisement-
    Play Games
  • 一:背景 1. 講故事 前些天有位朋友找到我,說他們的程式會偶發性的卡死一段時間,然後又好了,讓我幫忙看下怎麼回事?窗體類的程式解決起來相對來說比較簡單,讓朋友用procdump自動抓一個卡死時的dump,拿到dump之後,上 windbg 說話。 二:WinDbg 分析 1. 主線程在做什麼 要想 ...
  • 功能說明 使用ListView時,希望可以在單元格顯示圖片或其他控制項,發現原生的ListView不支持,於是通過拓展,實現ListView可以顯示任意控制項的功能,效果如下: 實現方法 本來想著在單元格裡面實現控制項的自繪的,但是沒找到辦法,最後是通過在單元格的錶面顯示對應控制項的,浮於錶面達到目的。 實 ...
  • 由於.NET Framework 4.0 是比較古老的版本,只有New Relic 7.0以下的版本才會支持.NET Framework 4.0的引用程式。 Technical support for .NET Framework 4.0 or lower 你可以參考這個官方Install New ...
  • 前言 隨著 DEV24.1.3 的發佈,XAF Blazor 中的屬性編輯器(PropertyEditor)也進行了很大的改動,在使用體驗上也更接近 WinForm 了,由於進行了大量的封裝,理解上沒有 WinForm 直觀,所以本文通過對屬性編輯器的原理進行解析,並對比新舊版本中的變化,使大家能夠 ...
  • OPC基金會提供了OPC UA .NET標準庫以及示常式序,但官方文檔過於簡單,光看官方文檔和示常式序很難弄懂OPC UA .NET標準庫怎麼用,花了不少時間摸索才略微弄懂如何使用,以下記錄如何從一個控制台程式開發一個OPC UA伺服器。 安裝Nuget包 安裝OPCFoundation.NetSt ...
  • 今天在技術群里,石頭哥向大家提了個問題:"如何在一個以System身份運行的.NET程式(Windows Services)中,以其它活動的用戶身份啟動可互動式進程(桌面應用程式、控制台程式、等帶有UI和互動式體驗的程式)"? 我以前有過類似的需求,是在GitLab流水線中運行帶有UI的自動化測試程 ...
  • .Net 中提供了一系列的管理對象集合的類型,數組、可變列表、字典等。從類型安全上集合分為兩類,泛型集合 和 非泛型集合,傳統的非泛型集合存儲為Object,需要類型轉。而泛型集合提供了更好的性能、編譯時類型安全,推薦使用。 ...
  • 在以前我做程式的時候,一般在登錄視窗裡面顯示程式名稱,登錄視窗一般設置一張背景圖片,由於程式的名稱一般都是確定的,所以也不存在太大的問題,不過如果客戶定製不同的系統的時候,需要使用Photoshop修改下圖層的文字,再生成圖片,然後替換一下也可以了。不過本著減少客戶使用繁瑣性,也可以使用空白名稱的通... ...
  • 一:背景 1. 講故事 在dump分析的過程中經常會看到很多線程卡在Monitor.Wait方法上,曾經也有不少人問我為什麼用 !syncblk 看不到 Monitor.Wait 上的鎖信息,剛好昨天有時間我就來研究一下。 二:Monitor.Wait 底層怎麼玩的 1. 案例演示 為了方便講述,先 ...
  • 目錄前言學習參考過程總結: 前言 做個自由仔。 學習參考 ChatGpt; https://www.cnblogs.com/zhili/p/DesignPatternSummery.html(大佬的,看了好多次) 過程 原由: 一開始只是想查查鏈式調用原理,以為是要繼承什麼介面,實現什麼方法才可以實 ...