![](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/)