透過 100+ 個技巧學習 Nuxt!

delay-hydration
nuxt-delay-hydration

透過延遲 hydration 改善您的 Nuxt v2 Google Lighthouse 分數。

nuxt-delay-hydration

NPM Downloads


狀態: 穩定 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 暗示的。

為了做到這一點,您可以確保

  • 初始回應中提供完整的 HTML
  • 腳本不會觸發 CLS
  • 避免使用腳本設定圖片,這會影響 LCP

此模組如何運作
一個 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 鍵下提供。

如果您發現實驗室或 現場數據 表現不佳,您可能需要調整此進階配置。

過濾路由

注意:建議使用路由規則而不是這些過濾選項。

使用 includeexclude 選項,您可以指定您想要在其上延遲 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 被封鎖,以及何時以及為何解除封鎖的詳細資訊。

基準測試

線上範例

貢獻者

贊助商

許可證

MIT 許可證 © 2022 - 至今 Harlan Wilton