模組熱替換

模組熱替換(HMR)可以在應用程式執行過程中交換、新增或刪除模組,而無需完全重新載入。這可以在幾個方面顯著加快開發速度

  • 保留在完全重新載入過程中丟失的應用程式狀態。
  • 僅更新已更改的內容,從而節省寶貴的開發時間。
  • 當原始碼中的 CSS/JS 發生修改時,立即更新瀏覽器,這幾乎與直接在瀏覽器開發者工具中修改樣式相當。

工作原理

讓我們從不同的角度來理解 HMR 的具體工作原理...

在應用程式中

以下步驟允許模組在應用程式中進行替換

  1. 應用程式請求 HMR 執行時檢查更新。
  2. 執行時非同步下載更新並通知應用程式。
  3. 應用程式隨後請求執行時應用更新。
  4. 執行時同步應用更新。

你可以設定 HMR 自動執行此過程,或者選擇要求使用者互動才能進行更新。

在編譯器中

除了常規資源外,編譯器還需要發出一個“更新”以允許從舊版本更新到新版本。“更新”由兩部分組成

  1. 更新後的 manifest (JSON)
  2. 一個或多個更新後的 chunk (JavaScript)

manifest 包含新的編譯雜湊和所有更新的 chunk 列表。每個 chunk 都包含所有更新模組的新程式碼(或表示模組已移除的標誌)。

編譯器確保這些構建之間模組 ID 和 chunk ID 的一致性。它通常將這些 ID 儲存在記憶體中(例如使用 webpack-dev-server),但也可以將其儲存在 JSON 檔案中。

在模組中

HMR 是一個可選功能,僅影響包含 HMR 程式碼的模組。一個例子是透過 style-loader 打補丁樣式。為了使補丁生效,style-loader 實現了 HMR 介面;當它透過 HMR 接收到更新時,它會將舊樣式替換為新樣式。

類似地,在模組中實現 HMR 介面時,你可以描述模組更新時應發生的情況。然而,在大多數情況下,不必在每個模組中編寫 HMR 程式碼。如果一個模組沒有 HMR 處理器,更新會向上冒泡。這意味著單個處理器可以更新完整的模組樹。如果樹中的單個模組更新,則整個依賴項集合會被重新載入。

有關 module.hot 介面的詳細資訊,請參閱HMR API 頁面

在執行時

這裡事情變得有點技術性... 如果你對內部細節不感興趣,可以直接跳到HMR API 頁面HMR 指南

對於模組系統執行時,會發出額外的程式碼來跟蹤模組的 父級子級。在管理方面,執行時支援兩種方法:checkapply

check 方法向更新 manifest 發出 HTTP 請求。如果此請求失敗,則沒有可用更新。如果成功,則會將更新的 chunk 列表與當前載入的 chunk 列表進行比較。對於每個已載入的 chunk,都會下載相應的更新 chunk。所有模組更新都儲存在執行時中。當所有更新 chunk 都已下載並準備好應用時,執行時會切換到 ready 狀態。

apply 方法將所有更新的模組標記為無效。對於每個無效模組,模組本身或其父級中需要有一個更新處理器。否則,無效標誌會向上冒泡並同樣使父級無效。每次冒泡都會繼續,直到達到應用程式的入口點或具有更新處理器的模組(以先達到者為準)。如果它從入口點冒泡,則該過程失敗。

之後,所有無效模組被處理(透過 dispose 處理器)並解除安裝。然後更新當前雜湊,並呼叫所有 accept 處理器。執行時切換回 空閒 狀態,一切恢復正常。

開始

HMR 可以在開發中用作 LiveReload 的替代品。webpack-dev-server 支援模式,在此模式下,它會嘗試使用 HMR 進行更新,然後再嘗試重新載入整個頁面。有關詳細資訊,請參閱模組熱替換指南

6 貢獻者

kryptokinghtSpaceK33zsokraGRardBrouzbeh84skipjack