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

 

 

一、是什麼

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機制,載入這兩個文件,並且針對修改的模組進行更新

參考文獻

  • //mp.weixin.qq.com/s?__biz=MzU1OTgxNDQ1Nw==&mid=2247487323&idx=1&sn=2ed2873cafb8b45062ca83922b38e866&chksm=fc10cd0dcb67441befcd19a1fb81fa6c11b3202532479998b3c51829c2c6c7e836f9d4a2ef47&scene=178&cur_album_id=1842744101150982149#rd
Tags: