Nuxt Vitalizer
作為一個專注做好一件事的 Nuxt 模組,收集一系列解決方案,以優化 Google Lighthouse 和 Google PageSpeed Insights 中的最大內容繪製 (LCP)。
此模組為以下 Nuxt 問題(以及其他問題)提供解決方案
- 停用動態導入的
prefetch
(#18376) - 預取區塊的優化 (#14584)
inlineStyles
選項導致 CSS 重複 (#21821)
功能
- 🚀 零配置即可獲得更好的 LCP
- 🫸 移除阻礙渲染的 CSS
- 🔥
DelayHydration
元件以減少阻塞時間指標 - 💨
SkipHydration
元件在初始渲染時保留 SSR 內容
設定
npx nuxi@latest module add nuxt-vitalizer
使用方式
將 Nuxt Vitalizer 新增至您的 Nuxt 設定,即可開始使用
// `nuxt.config.ts`
export default defineNuxtConfig({
modules: ['nuxt-vitalizer']
})
若要自訂模組,請在您的 Nuxt 設定中設定 vitalizer
選項
// `nuxt.config.ts`
export default defineNuxtConfig({
modules: ['nuxt-vitalizer'],
vitalizer: {
// Remove the render-blocking entry CSS
disableStylesheets: 'entry'
}
})
LCP 優化功能
套用此模組的優化功能後,您可以獲得更高的 Lighthouse 效能分數
停用動態導入的預取連結
!注意 此功能預設為啟用。
由於 HTML 中累積了 <link rel="prefetch">
標籤,大型 Nuxt 應用程式可能會在 Lighthouse 和 Google PageSpeed Insights 中出現效能分數不佳的情況。
對於每個動態導入,例如非同步元件和其他資源(例如圖片),都會渲染一個 prefetch
連結。這會導致瀏覽器預取這些區塊,即使它們在目前頁面上並不需要。雖然這對於應用程式的整體效能有益,但也可能導致大量預取請求,進而對最大內容繪製分數產生負面影響。
此模組會掛鉤到 Nuxt 建置流程,透過停用動態導入的 prefetch
連結的渲染來優化 LCP 分數。
停用預載連結
!注意 此功能必須手動啟用。
預載連結用於預載目前頁面所需的關鍵資源。雖然它們通常在優化網站效能方面有其作用,但如果使用不當,也可能導致大量請求。移除預載連結可以協助改善 FCP(首次內容繪製)分數,尤其是在網路條件不佳的情況下。
若要移除預載建置資源,請將 disablePrefetchLinks
選項設定為 true
// `nuxt.config.ts`
export default defineNuxtConfig({
modules: ['nuxt-vitalizer'],
vitalizer: {
disablePrefetchLinks: true
}
})
停止阻礙渲染的 CSS
!注意 此功能必須手動啟用。若要使用此功能,您需要啟用 Nuxt 的
inlineStyles
功能。啟用此選項後,請務必測試您的應用程式。
CSS 樣式表是阻礙渲染的資源,這表示瀏覽器必須先下載並剖析 CSS,才能渲染頁面。透過使用內嵌樣式而不是載入樣式表,瀏覽器可以更快地渲染頁面,進而改善 LCP 分數。
雖然最新版本的 Nuxt 在 SSR 渲染期間會內嵌樣式,但 entry.<hash>.css
樣式表仍會渲染在 HTML 中。這可能會導致阻礙渲染的 CSS,進而對最大內容繪製分數產生負面影響。
為什麼會這樣呢?正如 Nuxt 核心團隊成員 @danielroe 所解釋的
我認為這是目前內嵌樣式實作的限制。
您應用程式上每個地方使用的樣式可以安全地直接從 CSS 來源中完全移除。但是僅在一個元件或頁面中使用的 CSS 需要位於 CSS 檔案中,也需要內嵌。
目前,vite 完全負責在用戶端載入 CSS,這表示即使我們確實追蹤了已載入的 CSS,我們也無法阻止 vite 載入包含重複 CSS 的 CSS 檔案。
這絕對是我希望看到修正的問題。
首先,請嘗試在 app.vue
檔案中匯入主要應用程式樣式。當 Nuxt 建置時,它們將會儲存為 entry
CSS 檔案
// `app.vue`
import '~/assets/css/main.css'
現在,將 disableStylesheets
選項設定為 entry
,以防止 entry.<hash>.css
樣式表渲染在 HTML 中
// `nuxt.config.ts`
export default defineNuxtConfig({
modules: ['nuxt-vitalizer'],
vitalizer: {
disableStylesheets: 'entry'
}
})
元件
DelayHydration
!警告 延遲元件水合是一種技巧,可以欺騙 Lighthouse,使其認為頁面比實際情況更早可以互動。它可能無法提供實際的效能改進,因此應謹慎使用。
延遲水合是一種技巧,可以向 Lighthouse 暗示頁面比實際情況更早可以互動。這可以改善 Lighthouse 和 Google PageSpeed Insights 中的「阻塞時間」指標。
DelayHydration
元件是一個簡單的元件,它會在水合元件之前等待一段時間。當您有很多網路請求正在發生,並且想要延遲元件的水合直到網路請求完成時,這會很有用。
元件使用方式
在您的 Vue 元件中使用 DelayHydration
元件
<template>
<div>
<DelayHydration>
<!-- Ensure to lazy load the component -->
<LazyMyExpensiveComponent />
</DelayHydration>
</div>
</template>
設定
您可以在 vitalizer
模組選項中設定 DelayHydration
元件
// `nuxt.config.ts`
export default defineNuxtConfig({
modules: ['nuxt-vitalizer'],
vitalizer: {
delayHydration: {
hydrateOnEvents: ['mousemove', 'scroll', 'keydown', 'click', 'touchstart', 'wheel'],
idleCallbackTimeout: 8000,
postIdleTimeout: 4000
}
}
})
hydrateOnEvents
選項指定應觸發水合的事件。預設情況下,當使用者移動滑鼠、捲動、按下按鍵、按一下、觸摸螢幕或捲動滑鼠滾輪時,元件將立即水合。idleCallbackTimeout
選項指定在等待閒置回呼時要等待的最大時間(以毫秒為單位)。當有很多網路請求正在發生時,這會很有用。postIdleTimeout
選項指定在閒置回呼之後等待元件水合的時間(以毫秒為單位)。
SkipHydration
SkipHydration
元件只是阻止其子元件在初始渲染時於用戶端水合。換句話說,只要元件未卸載,就會保留 SSR 內容。當第一次造訪頁面時,沒有必要水合特定元件以節省載入元件區塊時,這會很有用。
當導覽到新頁面時,SkipHydration
元件將會在用戶端掛載其子元件,並且行為與一般 Vue 元件相同。
元件使用方式
在您的 Vue 元件中使用 SkipHydration
元件
<template>
<div>
<SkipHydration>
<!-- Ensure to lazy load the component -->
<LazyMyExpensiveComponent />
</SkipHydration>
</div>
</template>
模組選項
interface ModuleOptions {
/**
* Whether to remove prefetch links from the HTML. If set to `dynamicImports`, only dynamic imports will be removed. To disable all prefetching, such as images, set to `true`.
*
* @remarks
* This will prevent the browser from downloading chunks that may not be needed yet. This can be useful for improving the LCP (Largest Contentful Paint) score.
*
* @default 'dynamicImports'
*/
disablePrefetchLinks?: boolean | 'dynamicImports'
/**
* Whether to remove preload links from the HTML. This can be useful for improving the FCP (First Contentful Paint) score, especially when emulating slow network conditions.
*
* @default false
*/
disablePreloadLinks?: boolean
/**
* Whether to remove the render-blocking stylesheets from the HTML. This only makes sense if styles are inlined during SSR rendering. To only prevent the `entry.<hash>.css` stylesheet from being rendered, set to `entry`. If set to `true`, all stylesheet links will not be rendered.
*
* @remarks
* This requires to have the Nuxt `inlineStyles` feature enabled. Make sure to test your application after enabling this option.
*
* @default false
*/
disableStylesheets?: boolean | 'entry'
/**
* Options for the `DelayHydration` component.
*/
delayHydration?: {
/**
* Specify the events that should trigger hydration.
*
* @default ['mousemove', 'scroll', 'keydown', 'click', 'touchstart', 'wheel']
*/
hydrateOnEvents?: (keyof WindowEventMap)[]
/**
* The maximum amount of time to wait in milliseconds when waiting for an idle callback. This is useful when there are a lot of network requests happening.
*
* @default 8000
*/
idleCallbackTimeout?: number
/**
* Time to wait in milliseconds after the idle callback before hydrating the component.
*
* @default 4000
*/
postIdleTimeout?: number
}
}
💻 開發
- 複製此儲存庫
- 使用
corepack enable
啟用 Corepack - 使用
pnpm install
安裝相依性 - 執行
pnpm run dev:prepare
- 使用
pnpm run dev
啟動開發伺服器
鳴謝
- Nuxt GitHub 問題中所有啟發此模組的討論和貢獻。
- 感謝 @harlan-zw 啟發性的 nuxt-delay-hydration 模組。
授權
MIT 授權 © 2024-PRESENT Johann Schopplich