iT邦幫忙

2021 iThome 鐵人賽

DAY 4
2
Modern Web

今晚,我想來點 Web 前端效能優化大補帖!系列 第 4

Day04 X Core Web Vital & RAIL Model

在昨天介紹網頁檢測工具時,我們看到它提供了一些看起來十分專業的 Metrics,不過光看文字還真的猜不出它們代表的是什麼意思 ?

今天第一個段落會介紹三個評估使用者體驗的指標:LCP、FID、CLS,它們也被稱作 Core Web Vitals。

第二個段落則會介紹由 Google 提出且是「以使用者為中心」的用效能衡量指標 - RAIL Model。

Core Web Vitals

Google 根據長期以來大量的使用者體驗制定出了網站使用體驗的核心指標( Core Web Vital) ,Google 更指出若 75% 以上的使用者在網站中的瀏覽體驗都能夠通過以上 3 種指標,就能夠大幅的提升使用者的搜尋體驗,甚至能夠讓原本因等待而離開的使用者減少 24%!

雖然說這個指標是專門拿來評定使用者體驗的,不過經過前面幾天的介紹,大家應該早就了解前端應用的效能之於使用者體驗大概就像汽車的引擎之於整台車了,沒有馬力強大的引擎在背後運轉,設備再高級的進口車也終究只是單純拿來欣賞的擺飾。效能一塌糊塗的網站就算做的再漂亮再炫,使用者終究會因為沒有良好的體驗而選擇離開。

雖說網站效能只是 Core Web Vitals 列入的其中一個考量,然而藉由提升網站效能,我們可以提升 Core Web Vitals 的指標分數,進而改善使用者體驗,因此我認為 Core Web Vitals 是在做前端效能優化時不可或缺的參考指標。今天就來好好認識它們,並了解提升各個指標的方法吧!

LCP (Largest Contentful Paint ) — 顯示最大內容元素所需時間 [速度指標]

LCP 是計算網頁可視區 (viewport) 中最大元件的載入時間,也就是頁面的主要內容被使用者看到的時間,是速度的指標。

不過可視區內最大的元素並不是固定不變的

上圖的頁面在載入時一開始可視區的最大元素是左上角的文字,接下來隨著頁面載入變成了標題,最後變成了圖片,因為圖片是可視區最大的元素了,因此 LCP 就會以該圖片所需要載入的時間做計算。

目前會被 LCP API 考慮的 DOM 元件有:

  • <img> elements
  • 包在 <svg> element 裡面的 <image> elements
  • <video> elements
  • 透過 CSS url() 函式載入 background-image 的 element
  • 包含 text node 或是 inline-level text elements children 的 block-level element

如何優化 LCP

優化 LCP 的方法蠻直覺的,就是盡可能加快最大化元素 candidates 的載入速度,因此方法非常多元

減少伺服器回應時間

  • 針對主機效能優化
  • 使用地理位置較近的 CDN cache 靜態資源
  • 善用 Browser Cache
  • 提早載入第三方資源

盡量避免 Blocking Time

  • 降低 JavaScript blocking time
  • 降低 CSS blocking time

加快資源載入的時間

  • 圖片大小優化
  • 預先載入重要資源
  • 將文字檔案進行壓縮
  • 根據使用者的網路狀態提供不同的內容
  • 使用 service worker

避免使用客戶端渲染(CSR)

  • 若必須使用 CSR ,建議優化 JavaScript ,避免渲染時使用太多資源
  • 盡量在伺服器端完成頁面渲染,讓用戶端取得已渲染好的內容

想更了解 LCP 的眉眉角角的讀者可以參考LCP 官方文件

FID — First Input Delay 首次輸入延遲/封鎖時間總計 [互動性指標]

FID 用於測量使用者第一次對網站進行互動的時間,不過 FID 僅將單次互動例如滑鼠點擊,而不將畫面縮放,滑鼠滾動等連續性操作考慮進去。輸入延遲 (Input Delay) 通常發生於瀏覽器的主執行序(Main Thread)過度繁忙,而導致頁面內容無法正確地與使用者進行互動。舉例來說,可能瀏覽器正在載入一支相當肥大的 JavaScript 檔案,導致其他元素不能被載入而延遲可互動的時間。

例如,當你今天進入一個網頁時,發現網頁中有一個表單,你點擊輸入匡想要輸入文字,卻發現網站還沒完全載入完,網頁沒辦法馬上回應你的行為,點擊輸入匡卻完全沒有任何如 input focus 的反饋,也沒辦法輸入文字,這大大影響了使用者體驗,這就是 FID 所在意的針對互動性的時間衡量。

如何優化 FID

  • 減少 JavaScript 運作的時間
  • 降低網站的 request 數並降低檔案大小
  • 減少主執行序的工作
  • 降低第三方程式碼的影響

想更了解 FID 的眉眉角角的讀者可以參考FID 官方文件

CLS — Cumulative Layout Shift 累計版面配置轉移 [穩定性指標]

有沒有遇過一種情況是當你在網頁中準備點擊一個按鈕或連結的瞬間,突然間一個廣告插入或是跳出來,讓你不小心點開別的網站,恨的牙癢癢的呢?這就是 CLS 這個指標想要避免的不良體驗。

什麼情形會造成 CLS 分數不佳

Google 的官方文件指出幾點可能會造成 CLS 指數不佳的原因:

  • 圖片缺少初始尺寸,所以等載入後寬高才會長出來
  • 缺少尺寸的廣告、內嵌(embed)以及 iframe
  • 動態置入內容
  • 下載網站字體有機會造成頁面閃爍
  • 更新 DOM 前等待網路回應的動作

如何避免 CLS

CLS 這個指數本身就跟效能比較沒有關係了,他的解決方式也很直覺,例如給予會比較慢載入的元素一個預設的寬度與高度,就可以避免頁面 Layout 隨著資源載入跟著跳動。至於下載字體問題最簡單的解法是透過 preload 的 resource hint,這也會在未來的篇章介紹到。

CLS 的計算方式

LCP 跟 FID 都是用反應時間來當作指標,唯獨 CLS 是一個介於 0-1 之間的指標分數,那究竟這個分數是怎麼計算出來的呢?

元件移位分數(layout shift score) = 影響範圍(impact fraction) * 移動距離(distance fraction)

以上面這張圖為例子,這個元素偏移的影響範圍為整個螢幕長度的 75%,元件的移動距離為螢幕長度的 25%,因此此元素的 CLS 分數為 0.75*0.25 = 0.1875。(不過要精確一點的話還有一些要素要加進計算當中,但我們可以先忽略它)

然而這只是其中一個元素的分數,網站的 CLS 分數則是將所有發生位移的元件依上述公式算出來的值進行加總,一個穩定性良好的網站必須把加總的值控制在 0.1 以內才算合格。

我喜歡絢麗的動畫,會不會讓網站 CLS 變很高啊?

網頁的動畫常常使用到讓頁面元素移動的技巧,例如點選 Menu 展開更多選項的清單,那這樣會不會影響 CLS 分數啊?CLS 所在意的是「非預期的轉移」,所以如果頁面上的轉移動畫很明顯跟使用者互動有關,就不會被算進 CLS 裡喔!

想更了解 CLS 的眉眉角角的讀者可以參考CLS 官方文件


除了透過 Lighthouse 等網頁監測工具,還有沒有其他方式可以算出網站的 Core Web Vitals ?

當然有的,如果想知道還有什麼方式可以得出 Core Web Vitals 可以參考這裡

不過我認為一個蠻酷的方式是 Core Web Vitals 也推出 NPM Module 讓開發者可以透過程式得到這些指標啦!

import {getCLS, getFID, getLCP} from 'web-vitals';

function sendToAnalytics(metric) {
  const body = JSON.stringify(metric);
  // Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
  (navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
      fetch('/analytics', {body, method: 'POST', keepalive: true});
}

getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getLCP(sendToAnalytics);

RAIL Model

RAIL Model 是由 Google 所提出的一個效能指標,是一個「以使用者為中心」的模式,這個模型將使用者體驗細分成一些 key actions,例如 tap, scroll, load,並且協助我們更容易定義它們的效能指標,目標是讓使用者體驗可以更好。

RAIL 代表的是 Web App Life Cycle 裡的四個指標:

  • R : Response
  • A : Animation
  • I : Idle
  • L : Load

使用者對它們分別會有不同的期待與標準,來判斷一個網站的效能好不好。

Response : process events in under 50ms

根據一些可靠的研究所得出的結論,人類從操作行為到感知反應有 100 毫秒的間隔,也就是說使用者注意到延遲之前,我們有 100 毫秒的時間去回應使用者的行為。

咦?那為什麼上面寫 under 50ms ?

我們的目標是在 100ms 以內回應使用者的行為沒錯,那到底為什麼上面又寫 50ms 呢?原因在於通常除了處理使用者的 input 事件,瀏覽器還有其他的工作要做,而這些工作佔用了可接受輸入響應的部分可用時間。

考慮到這一點,可以安全地假設只有剩餘的 50 毫秒可用於實際處理使用者的 input 事件。下圖顯示了在 idle task 間收到的輸入如何排隊,從而減少了可用的處理時間

至於什麼是 idle task,為什麼是 idle task 是 50ms,等等會說明。

Animation: produce a frame in 10ms

目前大多數的裝置會以「每秒 60 次」的頻率重新整理螢幕,也就是每秒 60 幀(常常聽到別人說 frame rate 其實就是在指這個,常看到的 60 fps 代表的是 60 frames per second),才能讓使用者看到平順的動畫。這也就代表每一幀的時間只能花 16ms 左右 (一秒 1000ms / 60 = 16.66)。

咦?怎麼又來了,上面寫 10ms 耶!原因是因為瀏覽器大概需要 6ms 來渲染每一幀,所以才會說希望工作盡量在 10ms 內完成。如果超出這個標準太多或是幀率不穩定,浮動性很高,畫面便會開始出現抖動、卡頓,嚴重影響使用者體驗。

至於提升 frame rate 的方式,後面的篇章都會陸續提到,今天先有這個概念就夠了。

Idle: maximize idle time

目標是最大化的利用 idle time 以提升使用者的 input event 在 50ms 以內獲得回應的機會。

  • 我們可以利用 idle time 來做一些延遲的工作,像是為了加快頁面首次載入(Page Initial Load)的速度,可以盡可能在一開始載入少量但必要的資料,剩餘的資料可以利用 idle time 來載入。
  • 在 50ms 或更短的 idle time 內執行工作。如果超過 50ms,就有可能干擾網頁在 50ms 內響應使用者 input 的能力。
  • 如果使用者在 idle time 的工作期間與頁面交互,則使用者交互應始終具有最高的 priority 並中斷 idle time 的工作。

Load: deliver content and become interactive in under 5 seconds

經過 Day02 後我們知道頁面載入速度會大大影響使用者跳出率甚至影響企業的營收,所以能夠儘快載入頁面且讓使用者可以開始與之互動是很重要的目標。不過頁面載入速度其實也跟裝置的硬體資源與網路環境有關,所以 RAIL 根據使用者體驗的研究後訂出了一個目標:使用者在使用中低規格的 mobile device 且搭配緩慢的 3G 網路環境情況下,網站能夠在 5 秒內載入完畢且讓使用者可以開始與之互動,是一個效能好的網站需要達到的最低指標。

至於如何提升載入速度,也是未來篇章會慢慢介紹的。

RAIL Model 的介紹就到這邊,可能有讀者會疑問為什麼會出現一些奇怪的數字指標,像是 idle time 要在 50ms 內做完、頁面要在 5 秒內載入等等,還記得嗎?RAIL Model 是一個以「使用者為中心」的效能指標,這些數據指標都是大量的使用者經驗與數據經過整理與分析後得出的,個人覺得參考性蠻高的喔!
(使用者體驗真的又是一個非常博大精深的領域了)

本日小結

首先真的要感謝讀者看到今天還沒有左轉離開,因為目前為止都還沒有真的開始介紹效能優化的方法,而是在介紹效能優化的目的與參考指標,雖然些許乏味,不過我想讀者們一定明白這些觀念是非常重要的!相信讀者現在一定很清楚我們未來要進行的優化它們的目的到底是什麼了。

好消息!明天終於要正式進入介紹效能優化的各個技巧的章節了,不過別擔心,會先從最簡單的方式開始介紹,再慢慢深入到較需要花心思理解的技術,大家明天見!

References & 圖片來源

https://web.dev/vitals/
https://web.dev/vitals-tools/
https://web.dev/lcp/
https://web.dev/fid/
https://web.dev/cls/
https://www.youtube.com/watch?v=wO9GGY17NXY
https://ithelp.ithome.com.tw/articles/10187164
https://web.dev/rail/


上一篇
Day03 X Performance Analyzers feat. Lighthouse-CI
下一篇
Day05 X Code Minimize & Uglify
系列文
今晚,我想來點 Web 前端效能優化大補帖!30

尚未有邦友留言

立即登入留言