![](https://developers.google.com/static/search/blog/images/page-experience-signal.png?hl=zh-tw)
**Search signals** 為 Google 搜尋排名的考量指標之一,其中包含 Core Web Vitals 和 Mobile Friendly, HTTPS, No Intrusive Interstitials。
網站核心指標(Core Web Vitals)可以協助**評估網站的使用體驗**,並找出改進空間。若網站使用體驗不佳將會影響網站排名和SEO成效。
目前(2020年)**使用者體驗**專注於三個面向——**載入速度(loading performance)、互動反應能力(Interactivity)、視覺穩定性(Visual Stability)**,並根據這三個面向延伸出三個主要的指標:
- [Largest Contentful Paint(LCP)](https://web.dev/articles/lcp):測量從**網頁載入**到**頁面中最大面積元素渲染到畫面上**所花費的時間。
- [First Input Delay (FID)](https://web.dev/articles/fid):測量**使用者與網頁互動**,直到**瀏覽器回應互動事件**的時間差。
- [Cumulative Layout Shift (CLS)](https://web.dev/articles/cls):測量**累計佈局偏移**,即畫面發生未預期排版移動的程度。
這三項指向也是 Google 搜尋引擎排名的參考依據。
![image.png](https://hackmd.io/_uploads/SJMjbRWma.png)
>計劃在 2024 年 3 月,**Interaction to Next Paint (INP)** 會取代 FID 作為網站核心指標之一。https://web.dev/blog/inp-cwv
## 檢測網站體驗指標
CWV 檢測工具列表:
![](https://images.ctfassets.net/8er52l3j5u76/7wDmRRH5uanxggX4bSmipL/d0c3290821b40c7f24ff88b90d56aadf/Vitals-Tools1.png?fm=webp&q=80)
[PageSpeed Insights](https://pagespeed.web.dev) 提供單一網頁詳細的跑分報告,除了各項指標的分數之外還會提出具體的建議和改善方式。
統計的結果是 Google 在過去的這 28 天內真實使用者訪問網站的使用資料計算後得出。
![image.png](https://hackmd.io/_uploads/BJJn-AWQ6.png)
或者可以安裝 [Web Vitals](https://chrome.google.com/webstore/detail/web-vitals/ahfhijdlegdabablpippeagghigmibma) 這個擴展直接點擊進行測試。
![](https://lh3.googleusercontent.com/C5xY4eU7AXOhv_LI3GN-L2F3tDnhpZl2Q96NenSGXqGDAq8gQEwW0TuzHM7BMq9ZS1ZcRsJdPWbC3yiJEXQz1oFD5w=w640-h400-e365-rj-sc0x00ffffff)
![](https://i.imgur.com/kLgDEDL.png)
## Largest Contentful Paint (LCP)
測量從**網頁載入**到**看到的頁面中最大內容渲染**所花費的時間。
Google 建議的最佳載入時間是在 **2.5s** 內,**2.5s ~ 4.0s** 區間為需要改善,而超過 **4.0s** 就會導致使用者體驗變差。
![](https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/elqsdYqQEefWJbUM2qMO.svg)
### 最大內容的定義
**最大內容**包含:
1. `<img>` 元素
2. 含 `<image>` 的 `<svg>` 元素
3. 含預覽圖的 `<video>` 元素
4. 使用 CSS `url()` 載入的背景圖(不適用於 linear-gradient)
5. 文字段落標記區塊 (`<p>`)、清單 (`<ol>`、`<ul>`) 或標題 (`<h1>`、`<h2>`)
**圖片尺寸計算方式**為:
- 假設圖片**原始尺寸**為 100 x 100
- 縮小至 60 x 60 則以 60 x 60 計算
- 放大至 150 x 150 則以 100 x 100 計算
- **不**計算 padding, margin, border
簡單的說就是圖片總是以**最小尺寸**計算。
如果網頁中有**延遲載入的內容**,並且延遲載入的內容比當前最大內容還要更大,那 LCP 就會**重新計算**,直到使用者開始**與網頁互動(如:點擊、滾動)時 LCP 才會停止計算**。
以下是 LinkedIn 網站的載入方式,顯示 FCP 和 LCP,以及最大元素如何隨著內容載入而變化
![](https://assets-global.website-files.com/615b3ceb21dfc449a69b5204/615b47e145791c82703698a6_6157163af017e449c189bfa5_8.png)
### LCP 子項
LCP 總時間細分為下列子部分:
- **啟動第一個byte的時間(Time to first byte)**:TTFB,瀏覽器對 Server 發出請求後到收到 response data (第一個 byte) 所花的時間。
- **資源載入延遲(Resource load delay)**:TTFB 與瀏覽器開始載入 LCP 資源所花的時間。
- **資源載入時間(Resource load time)**:資源載入時間,載入 LCP 資源所花的時間。
- **元素渲染延遲(Element render delay)**:元素渲染延遲,LCP資源載入完成到 LCP 元素完全渲染前所花的時間。
![](https://web.dev/static/articles/optimize-lcp/image/a-breakdown-lcp-showing-23a709f16b362_856.png?hl=zh-tw)
### 測量 LCP
若要測量頁面的 LCP,可以使用 Chrome 開發者工具的「效能載入分析」,點擊「測量頁面載入速度」就會重新載入頁面並且分析頁面的載入效能。
![image.png](https://hackmd.io/_uploads/rk62-AWm6.png)
以維基百科首頁為例,測量後的結果如下圖所示,可以在右側看到載入的過程時間線,其中就包含了 LCP:
![chrome-performance.png](https://hackmd.io/_uploads/rkSrf0Z76.png)
點擊右側的 LCP 查看詳細內容,最下方還能看見 LCP 所包含的子項各耗費了多少時間:
![image.png](https://hackmd.io/_uploads/Sycp-CWma.png)
下圖則為 Github 的測量結果:
![image.png](https://hackmd.io/_uploads/ryeCb0bQp.png)
將滑鼠移到右邊的 LCP 就能在畫面上看到最大內容是哪一塊,比如根據測量結果 Github 首頁最大內容為 `img.home-campaign-lines-hero.position-relative`:
![image.png](https://hackmd.io/_uploads/SyePAW0WQp.png)
Github首頁 LCP 的各個子項耗時佔比計算:
- **啟動第一個byte的時間(TTFB)**: 65.668 / 576.894,佔比為 11.3%
- **資源載入延遲時間(Resource load delay)**: 221.299 / 576.894,佔比為 **38.3%**
- **資源載入時間(Resource load time)**: 0.065 / 576.894,佔比為 0.01%
- **元素渲染延遲(Element render delay)**: 289.862 / 576.894,佔比為 **50.2%**
![image.png](https://hackmd.io/_uploads/rJJ1zCWXp.png)
根據 web.dev 提供的最佳LCP子項時間, Resource load delay, Element render delay 這兩項超過了最佳化時間,不過 LCP 整體時間在最佳時間(2.5s)內,所以子項的耗時比例並不重要。
![image.png](https://hackmd.io/_uploads/BJUkMAbma.png)
### 延遲載入圖片
在圖片元素上加 `loading="lazy"` 可以延遲載入圖片,目的是改善使用者體驗。但某些情況下會惡化 LCP,從而[惡化使用者體驗](https://web.dev/articles/lcp-lazy-loading?hl=zh-tw),所以需要自行權衡。
解決方式:
1. 將 `loading="lazy"` 改為 `loading="eager"`或者不設置 `loading` 屬性。
2. 在首次載入時不延遲載入時可視範圍內的影像。
> [網頁瀏覽器層級的延遲載入圖片](https://web.dev/articles/browser-level-image-lazy-loading?hl=zh-tw#distance-from-viewport-thresholds)
### 優化 LCP
- 使用 CDN
- 使用 Cache
- 移除未使用的 CSS、延遲不重要的 CSS、壓縮 CSS (gzip, Brotli)
- 降低圖片尺寸、圖片使用 Webp 格式、壓縮圖片。
- 將資源標記成 `rel="preload"` 預先載入,如`<link rel="preload">``
- 將屬性 `rel="dns-prefetch"` 或 `rel="preconnect"` 新增至 `<link>` 可以通知瀏覽器網頁打算與另一個網域連接,並且在使用者點擊之前希望盡快執行此過程。
```html
<link rel=“preconnect” href=“https://example.com”/>
<link rel=“dns-prefetch” href=“https://example.com”/>
// Prefetch DNS for various other external assets Google Analytics, Google fonts, and even a CDN, as shown below.
<link rel=“dns-prefetch” href="//fonts.googleapis.com">
<link rel=“dns-prefetch” href="//www.google-analytics.com">
<link rel=“dns-prefetch” href="//cdn.domain.com">
```
- 為可能是網頁 LCP 元素的 `<img>` 上設定 `fetchpriority="high"`。將特定資源的優先順序設為優先,可以釋出更多頻寬來給需要更多的資源。
- 改為使用 SSR(Server-Side Rendering)。SSR 的主要缺點在於需要額外的伺服器處理時間,這可能會拖慢 TTFB,不過這種權衡取捨通常都是很值得的。
> 還有很多,詳細優化方式可以參考 web.dev 所寫的 [最佳化最大內容繪製](https://web.dev/articles/optimize-lcp?utm_source=devtools&hl=zh-tw#lcp-breakdown)
## First Input Delay (FID)
測量瀏覽器開始處理網頁上最初使用者互動(點連結、點按鈕、按壓鍵盤...等)所需的時間。
![](https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/eXyvkqRHQZ5iG38Axh1Z.svg)
![](https://assets-global.website-files.com/615b3ceb21dfc449a69b5204/615b47dcc6e7edf844c24555_6157027bc3b6bb31a89d87a9_croped-min.png)
通常來說 Input delay 主要是因為瀏覽器的 Main thread 在執行其他 JS 任務所以無法(尚未)回應使用者。
FID 通常會在 **首個內容繪製時間(FCP)** 和 **互動準備時間(TTI)** 之間,這代表著網頁已經render部分內容但還無法穩定地互動。
![](https://web.dev/static/articles/fid/image/example-page-load-trace-51d71647fee2c.svg?hl=zh-tw)
FCP 和 TTI 之間有相當長的時間 (包括三項長時間的任務),如果使用者在這段時間內嘗試與網頁互動 (例如點連結),那麼收到點擊後,從收到點擊到 Main thread 能夠回應的時間會有延遲。
![](https://web.dev/static/articles/fid/image/example-page-load-trace-461807023519a.svg?hl=zh-tw)
`<input>`、`<textarea>`、`<select>`、`<a>` 這些原生的 HTML 元素都需要等待 Main thread 上的進行中任務完成,才能回應使用者互動,因此也會在 FID 計算範圍內。
### 為什麼只考慮首次輸入
- FID 是使用者對網站回應的第一印象。
- 目前發現最大的互動問題是在網頁載入期間發生。
### First Input 考量的項目
FID 指標只會注重於**獨立動作**,例如點擊事件。其他連續動作(滾動、縮放...等)不會被考慮在其中,因為其效能限制截然不同。
這部分又涉及了 [RAIL 模型](https://web.dev/articles/rail?hl=zh-tw),**Response, Animation, Idle, Load**,上述提到的點擊事件為 Response,滾動、縮放則為 Animation,而 FID 會著重於 RAIL 模型中的 **Response**。
### 優化 FID
FID 主要是因爲繁重的 JS 執行任務佔用 Main thread,使瀏覽器無法處理使用者的互動行為事件,因此減少 Main thread 負擔可有效改善。
- 防抖(debounce), 節流(throttle)
- 延遲不重要的資源
- 壓縮資源
- 移除、延遲載入頁面時沒有使用到的JS
- 若要延遲載入 JS 可以在 script 加上 `defer` 屬性,在完成頁面渲染之後才會載入 JavaScript 檔案,如:` <script defer src="/example-js-script"></script>`
- [Code Splitting](https://bundlers.tooling.report/code-splitting/)
- [Unused Code Elimination](https://bundlers.tooling.report/transformations/dead-code/)
- [Unused Imported Code](https://bundlers.tooling.report/transformations/dead-code-dynamic/)
可以在 Chrome 開發者工具的涵蓋範圍(Coverage)查看哪些資源是當前頁面用不到的,可以將檔案分為多個小區塊,並使用 `defer` 延遲載入。
![image.png](https://hackmd.io/_uploads/BJcwQC-Qp.png)
如果在開發者工具中沒看到 Coverage 的頁籤,可以在右側找到**三個點-更多工具-涵蓋範圍(Coverage)**將它顯示出來:
![image.png](https://hackmd.io/_uploads/S1MO70-Q6.png)
## Cumulative Layout Shift (CLS)
CLS 用於評估網頁在整個生命週期發生的「**非預期**」佈局位移。
![](https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/9mWVASbWDLzdBUpVcjE1.svg)
和前面提到的 FCP, FID 不一樣,CLS 計算的是**位移量**而不是時間。
![](https://assets-global.website-files.com/615b3ceb21dfc449a69b5204/615b47d665fa1deb723a5cf5_6155e5762e5bc458ed88bb5c_6151b42bbbb7a245052935bf_7JlPVNGTio_dDfgEduz0FMUNw6JIec8EgaDQNj3GQWDRghZHDJfuxbCtpYlCs1OZrUj3YsT5r9Ge_VdzPH97ldUb6hB_qcfxvqY1I4f9ZOpCD0RjidbsMmeijmIsmIIUqR-nFwS0%25253Ds0.png)
### 計算位移量
若要計算位移量需要先知道**影響比例(impact fraction)、距離比例(distance fraction)**
- **影響比例(Impact fraction)**:計算不穩定佈局在移動前後共佔據 viewport 空間的比例。
- **距離比例(Distance fraction)**:計算佈局移動距離佔據 viewport 空間的比例。若水平和垂直皆位移則取大的位移量一方。
計算比例的方式為:`影響比例 x 距離比例`,數字越**低**越好。
以 web.dev 提供的例子說明,文本區塊最初佔據 viewport 50% 高度,而後垂直位移 25% viewport 高度,前後共佔了 75%,因此影響比例為 `0.75`。
![](https://web.dev/static/articles/cls/image/impact-fraction-example-164341c82ee76_1920.png?hl=zh-tw)
而剛剛前面有提到文本區塊是垂直向下位移了 25% viewport 高度,所以距離比例為 `0.25`。
套用位移計算公式,位移量為 `0.75*0.25 = 0.1875`,處在待優化的範圍內。
### 優化 CLS
- 為 img, video, iframe 標籤加上 width, height 屬性。
- 為延遲載入的內容預留空間,例如預留廣告區塊。
- 使用`<link rel=preload>` 提早下載字體,@font-face 加上 `font-display: optional` 。
- google fonts url 加上`&display=swap`。
- 盡量使用 transform 做動畫,瀏覽器運算成本較低。
- 使用 `transform: scale()` 而不是動畫變更 `height`, `width`
- 若要移動元素避免變更 `top`, `right`, `bottom`, `left`,可以使用 `transform: translate()`
## Interaction to Next Paint (INP)
> INP 將於 2024 年 3 月取代 FID 成為新的 Core Web Vitals 指標。
用於觀察使用者訪問網頁期間**所有點擊、輕觸和鍵盤互動的時間**,評估網頁的整體回應速度。INP 值為整個網頁生命週期內**耗時最長**的一個。
- **Good**: 0ms ~ 200ms
- **Needs improvement**: 200ms ~ 500ms
- **Poor**: 500ms ~ ?
### 為什麼要用 INP 取代 FID
FID 的缺點:
1. FID 僅會考量使用者的**首次**互動。
2. 它**不**包括所有類型的 user input(例如:滾動)。
3. 它**不**測量 user input 的整個處理時間(僅測量開始之前的**延遲**)。
![](https://web.dev/static/articles/better-responsiveness-metric/image/first-input-delay-measure-1b9438cf45be3.jpeg?hl=zh-tw)
Google 希望有一個新指標能:
1. 考量**所有** user input ,例如滾動
2. 測量事件的**整個持續時間**與**處理開始前的延遲**
3. 測量相關邏輯的一組事件的最大持續時間
4. 為網頁上的**所有互動**創建總分
### FID & INP
下圖為一個事件的生命週期,**FID 會衡量 (1) ~ (3) 花費的時間,而新的指標 INP 會衡量 (1) ~ (5) 花費的時間**。
![](https://web.dev/static/articles/better-responsiveness-metric/image/five-steps-the-lifecycle-987b4617bcdf8.jpeg?hl=zh-tw)
1. **輸入延遲(Input Delay)**:圖中的(1) ~ (3),是使用者與頁面首次互動到響應的延遲時間。
2. **處理時間(Processing time of Event Handler(s))**:圖中的(3) ~ (4),包括執行事件 callback 完成所需的時間。
3. **顯示延遲**:圖中的(5),也就是瀏覽器顯示下一個畫面 (包含互動影像結果) 所花費的時間。
### 優化 INP
- 最小化 DOM 大小
- 使用 content-visibility 延後顯示畫面外元素
- 使用 JS render HTML 時注意效能成本
> [How to Optimize LCP and Speed Index for Next.js Websites](https://medium.com/ne-digital/how-to-improve-lcp-and-speed-index-for-next-js-websites-f129ae776835)
## Reference
- [Core Web Vitals - web.dev](https://web.dev/articles/vitals?hl=zh-tw)
- [Largest Contentful Paint (LCP) - web.dev](https://web.dev/articles/lcp?hl=zh-tw)
- [最佳化最大內容繪製 - web.dev](https://web.dev/articles/optimize-lcp?utm_source=devtools&hl=zh-tw#1_eliminate_resource_load_delay)
- [First Input Delay(FID) - web.dev](https://web.dev/articles/fid?hl=en)
- [Cumulative Layout Shift (CLS) - web.dev](https://web.dev/articles/cls?hl=zh-tw)
- [Interaction to Next Paint (INP) - web.dev](https://web.dev/articles/inp?hl=en)
- [Advancing Interaction to Next Paint - web.dev](https://web.dev/blog/inp-cwv?hl=en)
- [Towards a better responsiveness metric - web.dev](https://web.dev/articles/better-responsiveness-metric?hl=en)
- [[前端優化系列]Web Vitals優化方法懶人包](https://gcdeng.com/blog/a-guidebook-to-optimize-web-vitals)
- [2021 行銷人與開發者都要懂的 SEO Core Web Vital](https://5xruby.tw/posts/seo-core-web-vitals)
- [認識SEO的排名因素:Page Experience 網頁體驗訊號](https://www.yesharris.com/seo-basic/seo-page-experience/)