nuxt-delay-hydration
狀態: 穩定 v2 v0 ✅ , v3 main ✅ 由我的 贊助計畫 💖 促成 追蹤我 @harlan_zw 🐦 |
⚠️ 這是一個「hack」技巧,用來欺騙 Google Lighthouse,使其認為您的網站比實際上更快。
- 它應該僅適用於漸進式增強網站。
- 它可能不會提供任何實際的效能或 SEO 效益(請使用 CrUX 進行測試,而不是 Google Lighthouse)。
功能
- 🔥 減少您網站的「封鎖時間」
- 🚦 使用路由規則進行頁面級別配置
- 🔁 (可選)重播 hydration 前的點擊
為何延遲 hydration?
延遲 hydration 是一種技巧,暗示 Google 我們的腳本並非應用程式運作所必需。
透過延遲 hydration,我們可以透過減少「封鎖時間」指標來改善 Google Lighthouse 分數。
先前您可能使用過 vue-lazy-hydration,它運作良好。但是,它只是一種更冗長的方式來向 Google 提供提示,就像我們使用此模組所做的那樣。
什麼是漸進式增強應用程式?
漸進式增強應用程式是一種設計為在沒有 JavaScript 的情況下也能運作,然後逐步使用 JavaScript 增強的應用程式。
您的網站應該不需要腳本就能使用,這就是我們透過延遲 hydration 向 Google 暗示的。
為了做到這一點,您可以確保
此模組如何運作
一個 Promise 會被注入到您的應用程式中,位置取決於模式。當以下任一事件觸發時,Promise 就會被解析
- 互動事件(滑鼠移動、滾動、點擊等)
- 具有固定超時時間的閒置回呼
閒置 CPU 時間向 Google 暗示,這些腳本並非您的應用程式運行所必需。
例如
- 如果 Google 機器人訪問頁面且沒有互動,在預設情況下,hydration 將不會發生,直到瀏覽器閒置回呼 + 6 秒
- 如果使用者訪問頁面並移動滑鼠游標或滾動,hydration 將立即被觸發。與非 hydration 應用程式互動的機會將會降到最低
請記住,這是一個權宜之計。在 Google 可以識別漸進式腳本增強功能之前,我們需要依賴這種方法。
安裝
如果您使用的是 Nuxt 2.x,請遵循 v0 分支上的文件。⚠️ Nuxt 2 已被棄用,將不再提供支援。
npx nuxi@latest module add delay-hydration
需求:漸進式增強的 SSR 或 SSG Nuxt 應用程式。
使用方式
// nuxt.config.ts
export default {
modules: [
'nuxt-delay-hydration',
],
delayHydration: {
// enables nuxt-delay-hydration in dev mode for testing
// NOTE: you should disable this once you've finished testing, it will break HMR
debug: process.env.NODE_ENV === 'development'
}
}
注意:除非您啟用 debug,否則模組不會在開發環境中運行。
選擇模式
預設情況下,未選擇任何模式,您需要選擇您希望模組如何運作。
類型: init
| mount
| manual
| false
預設值: false
類型 | 描述 | 使用案例 |
---|---|---|
false 預設 | 停用模組 | 測試 |
init | 延遲所有腳本的載入。 | 零個或最少的外掛程式/模組。 |
mount 建議 | 在 Nuxt 掛載時延遲它。外掛程式和一些第三方腳本將會運作。 | 最少非必要的和第三方外掛程式。 |
manual | 延遲由 DelayHydration 元件提供。 | 所有其他應用程式 |
無論您選擇哪種模式,請閱讀 進一步最佳化。
Init 模式
此模式會延遲所有腳本的載入,直到 hydration Promise 被解析。
它透過 Hook 到 HTML 渲染,移除所有 script 標籤,並在 hydration Promise 被解析後將它們重新添加回來。
這將提供最大的速度提升,但也是風險最高的。
優點: 提供最大的封鎖時間減少
缺點: 如果您有重要的第三方腳本,則有風險
基準測試: 約 90-100% 的減少
export default {
delayHydration: {
mode: 'init'
}
}
Mount 模式
此模式在 Nuxt 掛載時延遲它。外掛程式和一些第三方腳本將會運作。
這會延遲您的版面配置和頁面元件。
優點: 更安全且仍然提供良好的改善
缺點: 如果某些版面配置依賴 js,則可能仍然會中斷。
基準測試: 約 70% 的減少
export default {
delayHydration: {
mode: 'mount'
}
}
Manual 模式
使用 manual 模式,您可以手動指定您想要延遲應用程式的哪個部分。當您需要頁面的某些部分始終立即 hydration 時非常有用,例如導覽抽屜。
優點: 最安全的最佳化方式
缺點: 速度提升取決於使用情況
export default {
delayHydration: {
mode: 'manual'
}
}
DelayHydration 元件
設定模式後,您需要使用元件。
<template>
<div>
<DelayHydration>
<div>
<LazyMyExpensiveComponent />
</div>
</DelayHydration>
</div>
</template>
指南
每頁配置
您可以使用路由規則在每頁的基礎上配置模組。
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
// delay the home page
'/': { delayHydration: 'mount' },
// disable the module for the admin
'/admin/': { delayHydration: false }
}
})
您也可以使用 defineRouteRules 在頁面級別定義它們。
偵錯
Debug 模式
建議您在將模組部署到生產環境之前,對您的應用程式進行徹底的測試。
為了確保模組正在執行您期望的操作,有一個 debug
模式,啟用後將在控制台中記錄行為。
在您的本地環境中始終進行偵錯可能是個好主意,在這種情況下,您可以執行
export default defineNuxtConfig({
delayHydration: {
debug: process.env.NODE_ENV === 'development',
},
})
視覺化 hydration 狀態
有時可能不清楚您的應用程式是否已 hydration,如果它非常靜態,這可能會使偵錯變得困難。
為了讓事情更簡單,有一個元件 HydrationStatus
,它會告訴您正在發生的事情。
<template>
<div>
<MyHeader />
<DelayHydration>
<div>
<!-- Show the hydration status, only for debugging -->
<HydrationStatus />
<main>
<nuxt />
</main>
<my-footer />
</div>
</DelayHydration>
</div>
</template>
效能稽核
使用我的稽核工具:https://unlighthouse.dev/
重播 hydration 點擊
這是什麼以及如何啟用
延遲 hydration 的問題之一是,使用者互動事件可能會在您的腳本載入之前發生,導致使用者必須多次點擊某個東西才能使其執行他們期望的操作。想想使用 Javascript 觸發的漢堡選單,如果您的應用程式沒有 hydration,那麼點擊它將不會有任何作用。
針對這個問題的最佳解決方案是以「不需要 Javascript 的方式編寫 HTML」以使其具有互動性。
但是,在某些使用案例中,您需要使用 Javascript,並且回應第一次點擊非常重要。在這些情況下,您可以啟用點擊重播。
export default defineNuxtConfig({
delayHydration: {
replayClick: true
},
})
這是一個實驗性配置,您應該在將此選項實施到您的生產應用程式之前自行測試。
進一步最佳化
非同步載入重型元件
當您同步載入重型元件時,javascript 將與主要應用程式有效負載捆綁在一起。
這將降低您的所有效能指標。建議您對這些元件使用非同步導入。
運行 nuxi analyze
以查找大型元件。載入它們時,請以 Lazy
作為前綴。
進階配置
配置應在您的 Nuxt 配置中的 delayHydration
鍵下提供。
如果您發現實驗室或 現場數據 表現不佳,您可能需要調整此進階配置。
過濾路由
注意:建議使用路由規則而不是這些過濾選項。
使用 include
和 exclude
選項,您可以指定您想要在其上延遲 hydration 的路由。
// nuxt.config.ts
export default defineNuxtConfig({
delayHydration: {
include: [
'/blog/**',
],
exclude: [
'/admin/**'
],
},
})
您可以提供類似於路由規則的 glob 模式或正則表達式。
事件 Hydration
hydrateOnEvents
- 類型:
string[]
- 預設值:
[ 'mousemove', 'scroll', 'keydown', 'click', 'touchstart', 'wheel' ]
控制哪些瀏覽器事件應觸發 hydration 恢復。預設情況下,它相當積極,以避免可能的使用者體驗問題。
replayClick
- 類型:
boolean
- 預設值:
false
如果 hydration 的觸發器是點擊,您可以重播它。重播它將在假定您的應用程式已 hydration 後重新執行該事件。
例如,如果使用者點擊漢堡圖示,並且需要 hydration 才能打開選單,則它會在 hydration 後重播點擊。
⚠️ 這是實驗性的,請謹慎使用。
閒置 Hydration
idleCallbackTimeout
- 類型:
number
(毫秒) - 預設值:
7000
在等待閒置回呼時,可以定義等待的最長時間(以毫秒為單位)。當發生大量網路請求時,這非常有用。
postIdleTimeout
- 類型:
{ mobile: number, desktop: number }
(毫秒) - 預設值:
{ mobile: 5000, desktop: 4000, }
在閒置回呼後,我們恢復 hydration 之前,要等待多少時間(以毫秒為單位)。需要這個額外的超時時間來避免標準的「封鎖」,我們需要為 lighthouse 提供真正的閒置時間。
行動裝置應始終高於桌上型電腦,因為 CPU 容量通常會比桌上型電腦小得多。
注意:預設值將來可能會根據進一步的基準測試進行自訂。
偵錯
debug
- 類型:
boolean
- 預設值:
false
在控制台中記錄何時 hydration 被封鎖,以及何時以及為何解除封鎖的詳細資訊。
基準測試
線上範例
貢獻者
- Markus Oberlehner。Vue 中 lazy hydration 的先驅
贊助商
許可證
MIT 許可證 © 2022 - 至今 Harlan Wilton