前端效能指標全解析:LCP/FID/CLS/Core Web Vitals 實戰最佳化指南
性能优化(更新於 2026年5月14日)
Core Web Vitals:Google 的效能評分標準
2020 年 Google 推出 Core Web Vitals,作為搜尋排名的訊號:
| 指標 | 含義 | 好的閾值 | 需改進 | 差 |
|---|---|---|---|---|
| LCP | 最大內容繪製 | ≤2.5s | ≤4s | >4s |
| INP | 互動到下一次繪製 | ≤200ms | ≤500ms | >500ms |
| CLS | 累積版面配置位移 | ≤0.1 | ≤0.25 | >0.25 |
2024 年 3 月,INP 正式取代 FID 成為新的互動性指標。
LCP:最大內容繪製
什麼是 LCP?
LCP 測量頁面最大可見內容元素的渲染時間。通常是:
- 圖片(
<img>) - 背景圖(CSS
background-image) - 文字區塊(
<p>、<h1>) <video>海報圖
LCP 的四個階段
TTFB → 資源載入延遲 → 資源載入時間 → 元素渲染延遲
↑ ↑ ↑ ↑
伺服器 <link rel="preload> CDN 距離 關鍵 CSS/字型
回應時間 優先級/預載入 /壓縮 阻塞渲染
最佳化策略
1. 最佳化 TTFB
工具庫的 TTFB: ~50ms(CDN 直接回傳靜態 HTML)
對比 SSR 站點: 200-500ms(需要伺服器端渲染)
靜態匯出 + CDN 部署天然具有極低 TTFB。
2. 預載入關鍵資源
<link rel="preload" href="/fonts/geist-sans.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/i18n/toolClients/zh-CN.json" as="fetch" crossorigin />
工具庫在 layout.tsx 中預載入了工具用戶端資料 JSON。
3. 字型最佳化
// next.config.ts - 使用 npm 套件字型而非 Google Fonts CDN
// 避免:國內存取 fonts.googleapis.com 經常 ECONNRESET
import { GeistSans } from 'geist/font/sans';
4. 圖片最佳化
對於工具站的 LCP 元素(通常是首屏文字),圖片不是主要瓶頸。但部落格文章中的配圖需要:
<img
src="photo.webp"
loading="eager" <!-- LCP 圖片不用 lazy -->
fetchpriority="high" <!-- 優先級最高 -->
decoding="async" <!-- 非同步解碼 -->
/>
INP:互動到下一次繪製
從 FID 到 INP
FID 只測量首次互動的延遲,忽略互動的處理時間。INP 測量所有互動的全週期:
使用者點擊/按鍵
↓
輸入事件開始
↓
事件處理函式執行(JS)
↓
樣式/版面配置計算
↓
繪製
↓
INP = 從輸入開始到繪製完成的時間
常見 INP 問題
主執行緒長任務
// 差:同步處理大資料阻塞主執行緒
function processData(data) {
const result = heavyComputation(data); // 阻塞 500ms
updateUI(result);
}
// 好:分片處理或放入 Worker
async function processData(data) {
const result = await processInWorker(data); // 不阻塞 UI
updateUI(result);
}
React 狀態更新導致重渲染
// 差:大列表全量重渲染
setFilter(keyword); // 1000 個工具卡片全部重渲染
// 好:虛擬化 + useMemo
const filtered = useMemo(
() => tools.filter(t => t.name.includes(keyword)),
[tools, keyword]
);
工具庫的 INP 最佳化
- 搜尋使用預產生索引:建置時產生
tools-search/zh-CN.json,搜尋時直接查索引,無需遍歷所有工具 - WASM 處理放入 Worker:FFmpeg.wasm 操作在 Worker 執行緒執行
- React.lazy 懶載入:工具頁面元件按需載入,減少主套件體積
CLS:累積版面配置位移
CLS 的計算
CLS = Σ (影響分數 × 距離分數)
影響分數:偏移元素占視窗面積的比例
距離分數:偏移距離占視窗尺寸的比例
常見 CLS 來源
| 來源 | 範例 | 修復 |
|---|---|---|
| 圖片無尺寸 | <img src="..."> |
設定 width/height 或 aspect-ratio |
| 動態注入內容 | 廣告/推薦延遲載入 | 預留空間 (min-height) |
| Web Font FOIT | 字型載入時文字不可見 → 可見 | font-display: swap + 尺寸回退 |
| 非同步 UI 元件 | 搜尋框/彈窗延遲渲染 | min-height 預留空間 |
工具庫的 CLS 最佳化
/* 導覽列固定高度,避免載入時跳動 */
nav[data-tools-nav] {
/* 高度由 JS 測量後設定 CSS 變數 */
}
/* 底欄固定高度 */
:root {
--site-footer-h: 33px;
}
body {
padding-bottom: var(--site-footer-h);
}
測量工具
實驗室資料(Lab)
| 工具 | 用途 |
|---|---|
| Lighthouse | CI 自動化稽核 |
| Chrome DevTools Performance | 逐幀分析 |
| WebPageTest | 多地點/多裝置測試 |
現場資料(Field)
| 工具 | 用途 |
|---|---|
| Chrome UX Report (CrUX) | Google 的真實使用者資料 |
| web-vitals JS 函式庫 | 自建現場資料採集 |
| Google Search Console | Core Web Vitals 評分報告 |
使用 web-vitals 函式庫採集
import { onLCP, onINP, onCLS } from 'web-vitals';
onLCP((metric) => {
// 傳送到 GA4
gtag('event', 'web_vital', {
name: 'LCP',
value: metric.value,
rating: metric.rating,
});
});
onINP((metric) => { /* ... */ });
onCLS((metric) => { /* ... */ });
工具庫的效能資料
基於 Lighthouse 測試(模擬 4x 降速 + 桌面):
| 指標 | 數值 | 評級 |
|---|---|---|
| Performance | 95 | 🟢 |
| LCP | 1.2s | 🟢 Good |
| INP | 80ms | 🟢 Good |
| CLS | 0.02 | 🟢 Good |
| TTFB | 50ms | 🟢 Good |
| FCP | 0.8s | 🟢 Good |
| TTI | 1.5s | 🟢 Good |
效能優勢來源
- 純靜態 HTML:CDN 直接回傳,TTFB 極低
- 無用戶端渲染等待:Server Components 預先渲染
- 按需載入 WASM:不進入影片工具頁不載入 30MB FFmpeg
- 字型本地化:避免 Google Fonts CDN 延遲/失敗
- 預載入關鍵資源:搜尋索引、工具資料 JSON
最佳化檢查清單
LCP 最佳化
- 確認 LCP 元素(DevTools → LCP 標記)
- 預載入 LCP 圖片/字型
- CDN 部署,降低 TTFB
- 壓縮關鍵 CSS(內嵌首屏樣式)
- 使用
fetchpriority="high"標記 LCP 資源
INP 最佳化
- 識別長任務(DevTools → Long Tasks)
- 將計算移入 Web Worker
- 使用
requestIdleCallback延遲非緊急工作 - React:
useMemo/useCallback/ 虛擬化
CLS 最佳化
- 圖片設定
width+height或aspect-ratio - 字型使用
font-display: swap+size-adjust - 動態內容預留空間
- 避免
document.body.appendChild導致版面配置位移
總結
Core Web Vitals 不僅是 Google 排名因素,更是使用者體驗的客觀度量。工具庫透過靜態匯出 + CDN + 預載入 + Worker 卸載 + 字型本地化的組合策略,實現了 LCP < 1.5s、INP < 100ms、CLS < 0.05 的高效能表現。
本站提供瀏覽器本地工具,免註冊即可試用 →
#性能#Core Web Vitals#LCP#INP#CLS