HMR API
注意
這是用戶端 HMR API。如需在外掛中處理 HMR 更新,請參閱 handleHotUpdate。
手動 HMR API 主要用於框架和工具的作者。作為最終用戶,HMR 很可能已在特定框架的入門範本中為您處理。
Vite 透過特殊的 import.meta.hot
物件公開其手動 HMR API。
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
if (import.meta.hot) {
// HMR code
}
TypeScript 的 IntelliSense
Vite 在 vite/client.d.ts
中提供 import.meta.hot
的類型定義。您可以在 src
目錄中建立一個 env.d.ts
,以便 TypeScript 取得類型定義。
/// <reference types="vite/client" />
hot.accept(cb)
若要讓模組自行接受更新,請使用 import.meta.hot.accept
並帶有一個回呼函式,該函式會接收更新後的模組。
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)
模組也可以接受直接依賴項的更新,而無需重新載入自身。
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
來清理其更新副本建立的任何持續性副作用。
function setupSideEffect() {}
setupSideEffect()
if (import.meta.hot) {
import.meta.hot.dispose((data) => {
// cleanup side effect
})
}
hot.prune(cb)
註冊一個回呼函式,該函式將在頁面上不再匯入該模組時呼叫。與 hot.dispose
相比,如果原始碼在更新時自行清理副作用,並且您只需要在將其從頁面中移除時進行清理,則可以使用此方法。Vite 目前將此用於 .css
匯入。
function setupOrReuseSideEffect() {}
setupOrReuseSideEffect()
if (import.meta.hot) {
import.meta.hot.prune((data) => {
// cleanup side effect
})
}
hot.data
import.meta.hot.data
物件會在同一個更新模組的不同實例之間持續存在。它可以用於將資訊從模組的先前版本傳遞到下一個版本。
請注意,不支援重新分配 data
本身。相反地,您應該變更 data
物件的屬性,以便保留從其他處理常式新增的資訊。
// 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
,如下所示:
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 以及其底層運作方式。請查看以下資源: