跳至內容

HMR API

注意

這是用戶端 HMR API。如需在外掛中處理 HMR 更新,請參閱 handleHotUpdate

手動 HMR API 主要用於框架和工具的作者。作為最終用戶,HMR 很可能已在特定框架的入門範本中為您處理。

Vite 透過特殊的 import.meta.hot 物件公開其手動 HMR API。

ts
interface ImportMeta {
  readonly 
hot
?: ViteHotContext
} interface ViteHotContext { readonly
data
: any
accept
(): void
accept
(
cb
: (
mod
:
ModuleNamespace
| undefined) => void): void
accept
(
dep
: string,
cb
: (
mod
:
ModuleNamespace
| undefined) => void): void
accept
(
deps
: readonly string[],
cb
: (
mods
:
Array
<
ModuleNamespace
| undefined>) => void,
): void
dispose
(
cb
: (
data
: any) => void): void
prune
(
cb
: (
data
: any) => void): void
invalidate
(
message
?: string): void
on
<
T
extends string>(
event
:
T
,
cb
: (
payload
:
InferCustomEventPayload
<
T
>) => void,
): void
off
<
T
extends string>(
event
:
T
,
cb
: (
payload
:
InferCustomEventPayload
<
T
>) => void,
): void
send
<
T
extends string>(
event
:
T
,
data
?:
InferCustomEventPayload
<
T
>): void
}

必要的條件保護

首先,請務必使用條件區塊保護所有 HMR API 用法,以便程式碼可以在生產環境中進行 tree-shaking

js
if (import.meta.hot) {
  // HMR code
}

TypeScript 的 IntelliSense

Vite 在 vite/client.d.ts 中提供 import.meta.hot 的類型定義。您可以在 src 目錄中建立一個 env.d.ts,以便 TypeScript 取得類型定義。

ts
/// <reference types="vite/client" />

hot.accept(cb)

若要讓模組自行接受更新,請使用 import.meta.hot.accept 並帶有一個回呼函式,該函式會接收更新後的模組。

js
export const 
count
= 1
if (import.meta.
hot
) {
import.meta.
hot
.
accept
((
newModule
) => {
if (
newModule
) {
// newModule is undefined when SyntaxError happened
console
.
log
('updated: count is now ',
newModule
.count)
} }) }

「接受」熱更新的模組被視為一個 HMR 邊界

Vite 的 HMR 實際上不會交換原始匯入的模組:如果 HMR 邊界模組重新匯出依賴項的匯入,則它有責任更新這些重新匯出的內容(而且這些匯出必須使用 let)。此外,來自邊界模組的上層匯入器不會收到變更通知。這種簡化的 HMR 實作對於大多數開發用例來說已足夠,同時也允許我們跳過產生代理模組的昂貴工作。

Vite 要求此函式的呼叫在原始碼中顯示為 import.meta.hot.accept((對空格敏感),模組才能接受更新。這是 Vite 進行靜態分析的要求,以便為模組啟用 HMR 支援。

hot.accept(deps, cb)

模組也可以接受直接依賴項的更新,而無需重新載入自身。

js
import { 
foo
} from './foo.js'
foo
()
if (import.meta.
hot
) {
import.meta.
hot
.
accept
('./foo.js', (
newFoo
) => {
// the callback receives the updated './foo.js' module
newFoo
?.foo()
}) // Can also accept an array of dep modules: import.meta.
hot
.
accept
(
['./foo.js', './bar.js'], ([
newFooModule
,
newBarModule
]) => {
// The callback receives an array where only the updated module is // non null. If the update was not successful (syntax error for ex.), // the array is empty }, ) }

hot.dispose(cb)

自我接受的模組或預期被其他模組接受的模組可以使用 hot.dispose 來清理其更新副本建立的任何持續性副作用。

js
function 
setupSideEffect
() {}
setupSideEffect
()
if (import.meta.
hot
) {
import.meta.
hot
.
dispose
((
data
) => {
// cleanup side effect }) }

hot.prune(cb)

註冊一個回呼函式,該函式將在頁面上不再匯入該模組時呼叫。與 hot.dispose 相比,如果原始碼在更新時自行清理副作用,並且您只需要在將其從頁面中移除時進行清理,則可以使用此方法。Vite 目前將此用於 .css 匯入。

js
function 
setupOrReuseSideEffect
() {}
setupOrReuseSideEffect
()
if (import.meta.
hot
) {
import.meta.
hot
.
prune
((
data
) => {
// cleanup side effect }) }

hot.data

import.meta.hot.data 物件會在同一個更新模組的不同實例之間持續存在。它可以用於將資訊從模組的先前版本傳遞到下一個版本。

請注意,不支援重新分配 data 本身。相反地,您應該變更 data 物件的屬性,以便保留從其他處理常式新增的資訊。

js
// ok
import.meta.
hot
.
data
.someValue = 'hello'
// not supported import.meta.
hot
.
data
= {
someValue
: 'hello' }

hot.decline()

目前這是一個空操作,存在是為了向後相容性。如果未來有新的用途,這可能會變更。若要指示模組不可熱更新,請使用 hot.invalidate()

hot.invalidate(message?: string)

自我接受的模組可能會在執行階段意識到它無法處理 HMR 更新,因此更新需要強制傳播到匯入器。透過呼叫 import.meta.hot.invalidate(),HMR 伺服器將使呼叫者的匯入器失效,如同呼叫者沒有自我接受一樣。這會在瀏覽器主控台和終端機中記錄訊息。您可以傳遞訊息,以提供有關失效原因的一些內容。

請注意,即使您打算立即呼叫 invalidate,也應始終呼叫 import.meta.hot.accept,否則 HMR 用戶端不會監聽自我接受模組的未來變更。為了清楚地傳達您的意圖,我們建議在 accept 回呼函式中呼叫 invalidate,如下所示:

js
import.meta.
hot
.
accept
((
module
) => {
// You may use the new module instance to decide whether to invalidate. if (cannotHandleUpdate(
module
)) {
import.meta.
hot
.
invalidate
()
} })

hot.on(event, cb)

監聽 HMR 事件。

下列 HMR 事件由 Vite 自動分派:

  • 'vite:beforeUpdate' 當即將套用更新時(例如,模組將被取代)
  • 'vite:afterUpdate' 當剛套用更新時(例如,模組已被取代)
  • 'vite:beforeFullReload' 當即將發生完整重新載入時
  • 'vite:beforePrune' 當即將修剪不再需要的模組時
  • 'vite:invalidate' 當模組透過 import.meta.hot.invalidate() 失效時
  • 'vite:error' 當發生錯誤時(例如,語法錯誤)
  • 'vite:ws:disconnect' 當 WebSocket 連線遺失時
  • 'vite:ws:connect' 當 WebSocket 連線(重新)建立時

自訂 HMR 事件也可以從外掛傳送。如需詳細資訊,請參閱 handleHotUpdate

hot.off(event, cb)

從事件監聽器中移除回呼函式。

hot.send(event, data)

將自訂事件傳回 Vite 的開發伺服器。

如果在連線之前呼叫,資料將會被緩衝,並在連線建立後傳送。

如需詳細資訊,請參閱 用戶端伺服器通訊,包括關於 為自訂事件輸入類型 的章節。

延伸閱讀

如果您想深入瞭解如何使用 HMR API 以及其底層運作方式。請查看以下資源:

在 MIT 授權下發佈。(ccee3d7c)