Stories

Detail Return Return

Web 頁面性能衡量指標-以用户為中心的性能指標 - Stories Detail

Web 頁面性能衡量指標-以用户為中心的性能指標

以用户為中心的性能指標是理解和改進站點體驗的關鍵點

一、以用户為中心的性能指標

1. 指標是用來幹啥的?

指標是用來衡量性能和用户體驗的

2. 指標類型

  • 感知加載速度:網頁可以多快地加載網頁中的所有視覺元素並將其渲染到屏幕上
  • 加載響應速度:頁面加載和執行組件快速響應用户互動所需的 JavaScript 代碼的速度
  • 運行時響應速度:網頁在加載後對用户互動的響應速度
  • 視覺穩定性:頁面上的元素是否會以用户意想不到的方式發生偏移,是否可能會干擾用户的互動?
  • 流暢性:過渡和動畫是否以一致的幀速率渲染,並在一種狀態之間流暢地流動?

3. 要衡量的指標

3.1. FCP(First Contentful Paint)

從網頁開始加載到網頁內容的任何部分呈現在屏幕上所用的時間

3.2. LCP(Largest Contentful Paint)

從網頁開始加載到屏幕上呈現最大的文本塊或圖片元素所用的時間

3.3. INP(Interaction to Next Paint)

與網頁進行的每次 tapclick 或鍵盤互動的延遲時間

並根據交互的數量選擇頁面中最差的交互延遲作為單個代表性值來描述頁面的總體響應性

3.4. TBT(Total Blocking Time)

FCP 到可交互時間 (TTI) 之間的總時長

3.5. CLS(Cumulative Layout Shift)

從頁面開始加載到其生命週期狀態更改為隱藏期間發生的所有意外佈局偏移的累計分數

3.6. TTFB(Time to First Byte)

網絡使用資源的第一個字節響應用户請求所花費的時間

3.7. FID(First Input Delay)

用户首次與網頁互動(即,點擊鏈接、點按按鈕或使用由 JavaScript 提供支持的自定義控件)到瀏覽器實際能夠開始處理事件處理腳本以響應相應互動的時間

二、FCP(First Contentful Paint )

1. 什麼是 FCP?

FCP:從網頁開始加載到網頁內容的任何部分呈現在屏幕上所用的時間。

首次內容繪製 (FCP) 是一項以用户為中心的重要指標,用於衡量感知的加載速度。

它標記了網頁加載時間軸中用户可以看到屏幕上任何內容的第一個點。

FCP 衡量的是從用户首次導航到相應網頁到該網頁的任何部分呈現在屏幕上所用的時間。對於此指標,內容是指文本、圖片(包括背景圖片)、<svg> 元素或非白色 <canvas> 元素。

2. FCP

image

FCP 在第二幀發生,因為這是第一個文本元素渲染到屏幕上的時間

3. 良好的 FCP 是多少時間?

為了提供良好的用户體驗,網站的 FCP 最好不超過 1.8 秒。

較好的 FCP 值為 1.8 秒或更短。較差超過 3.0 秒。

在這裏插入圖片描述

4. 如何衡量 FCP?

  • PageSpeed Insights
  • Chrome 用户體驗報告
  • web-vitals JavaScript
  • Lighthouse
  • Chrome DevTools
  • PerformanceObserver 方法

5. 衡量 JS 中的 FCP

如需在 JavaScript 中測量 FCP,需使用 Paint Timing API

5.1. 簡單示例:
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntriesByName('first-contentful-paint')) {
    console.log('FCP candidate:', entry.startTime, entry);
  }
}).observe({type: 'paint', buffered: true});

image

5.2. 指標與 API 的區別
  • API 會為後台標籤頁中加載的網頁分派 first-contentful-paint ,但在計算 FCP 時應忽略這些網頁。只有當網頁始終在前台運行時,系統才會考慮首次渲染時間。
  • 從往返緩存中恢復網頁時,API 不會報告 first-contentful-paint ,但在這些情況下,應衡量 FCP,因為用户將它們視為不同的網頁訪問。
  • API 可能不會報告跨源 iframe 的繪製時間,但為了正確衡量 FCP,必須考慮所有幀。子幀可以使用該 API 將其繪製時間報告給父幀以進行彙總。
  • API 從導航啓動時開始測量 FCP,但對於預渲染的網頁,應通過 activationStart 測量 FCP
5.3. 使用 web-vitals JavaScript 庫來衡量 FCP

使用 web-vitals JavaScript 庫來衡量 FCP,而無需記住所有這些細微差異,該庫會盡可能處理這些差異

import {onFCP} from 'web-vitals';

onFCP(console.log);

onFCP 源碼

6. 如何提高 FCP?

6.1. 提高特定網站的 FCP

可以運行 Lighthouse 性能審核,並關注審核建議的任何特定 opportunities 或者 diagnostics

6.2. 總體提高 FCP
  • 移除阻塞渲染的資源
  • 縮減 CSS 大小
  • 移除未使用的 CSS
  • 移除未使用的 JavaScript
  • 預先連接到所需的源
  • 縮短服務器響應時間 (TTFB)
  • 避免多次網頁重定向
  • 預加載密鑰請求
  • 避免網絡負載龐大
  • 採用高效的緩存政策提供靜態資源
  • 避免 DOM 規模過大
  • 最大限度地縮短關鍵請求深度
  • 確保文本在網頁字體加載期間保持可見狀態
  • 儘量減少請求數量,減少傳輸大小

三、LCP(Largest Contentful Paint )

1. 什麼是 LCP?

LCP:從網頁開始加載到屏幕上呈現最大的文本塊或圖片元素所用的時間

LCP 報告的是窗口中可見最大圖片或文本塊相對於用户首次導航到網頁的呈現時間

LCP 包含從上一個網頁開始的所有卸載時間、連接設置時間、重定向時間和首字節時間 (TTFB)

2. 良好的 LCP 是多少時間?

為了提供良好的用户體驗,網站應努力將 LCP 控制在 2.5 秒以內。

在這裏插入圖片描述

2.5 s 或者更短

3. 需要考慮哪些元素?

Largest Contentful Paint 考慮的元素類型包括:

  • <img> 元素(第一幀呈現時間用於 GIF 或動畫 PNG 等動畫內容)
  • <svg> 元素內的 <image> 元素
  • <video> 元素(系統會使用視頻的海報圖片加載時間或第一幀顯示時間,以較早者為準)
  • 一個元素,帶有使用 url() 函數加載的背景圖片
  • 包含文本節點或其他內嵌級文本元素子元素的塊級元素。

後面可能會增加其他元素

4. 如何確定元素的大小?

LCP 報告的元素的大小通常是用户在窗口中可見的大小,如果元素延伸到窗口之外,或者元素被剪切或有不可見的溢出,這些部分不計入元素的大小。

對於根據固有尺寸調整過大小的圖片元素,報告的尺寸為可見尺寸或固有尺寸(以較小者為準)。

對於文本元素,LCP 只會考慮能夠包含所有文本節點的最小矩形。

對於所有元素,LCP 都不會考慮使用 CSS 應用的外邊距、內邊距或邊框。

5. 什麼時候報告 LCP?

網頁通常會分階段加載,因此,網頁上最大的元素可能會發生變化。

為了應對這種可能發生的變化,瀏覽器在繪製完第一幀後,會立即分派 largest-contentful-paint 類型的 PerformanceEntry,用於標識鏈接最大的內容元素,在渲染後續幀後,只要最大內容元素髮生變化,它就會再分派一個 PerformanceEntry

元素只有在呈現並對用户可見後,才能被視為最大的內容元素。尚未加載的圖片不會被視為已渲染。在字體屏蔽期間,文本節點也不會使用網頁字體。在這種情況下,系統可能會將較小的元素報告為最大的內容元素,但如果這個較大的元素呈現完畢,系統便會創建另一個 PerformanceEntry

除了延遲加載圖片和字體之外,網頁還可能會在新內容可用時向 DOM 添加新元素。如果這些新元素中的任何一個大於之前的最大內容元素,系統還會報告新的 PerformanceEntry

如果從窗口甚至 DOM 中移除了最大的內容元素,除非渲染了較大的元素,否則它仍然是最大的內容元素

一旦用户與網頁互動(通過點按、滾動或按鍵),瀏覽器就會停止報告,因為用户互動通常會改變向用户顯示的內容(特別是滾動時)。

6. 如何衡量 LCP?

  • Chrome User Experience Report
  • PageSpeed Insights
  • web-vitalsJavaScript library
  • Chrome DevTools
  • Lighthouse
  • WebPageTest
  • PerformanceObserver 方法

7. 在 JS 中衡量 LCP

7.1. 簡單示例
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    console.log('LCP candidate:', entry.startTime, entry);
  }
}).observe({type: 'largest-contentful-paint', buffered: true});

image

7.2. 指標與 API 的區別
  • API 將為後台標籤頁中加載的頁面分派 largest-contentful-paint,但在計算 LCP 時應忽略這些頁面。
  • 在頁面進入後台後,API 將繼續分派 largest-contentful-paint,但在計算 LCP 時應忽略這些(只有在頁面始終在前台運行時才可以考慮元素)。
  • 從往返緩存中恢復網頁時,該 API 不會報告 largest-contentful-paint ,但應在在這些情況下衡量 LCP ,因為用户對它們的訪問體驗是不同的。
  • API 不會考慮 iframe 中的元素,但該指標會考慮,因為它們是網頁用户體驗的一部分。
  • API 從導航開始就測量 LCP,但對於預渲染的網頁,LCP 應從 activationStart 開始測量,因為 LCP 對應於用户實際體驗到的 LCP 時間。
7.3. 使用 web-vitals JavaScript 庫衡量 LCP

可以使用 web-vitalsJavaScript 庫來衡量 LCP,而無需記住所有這些細微差異

import {onLCP} from 'web-vitals';

onLCP(console.log);

onLCP 源碼

8. 如何提高 LCP?

  • 消除加載延遲
  • 消除元素渲染延遲
  • 縮短資源加載時長
  • 縮短第一個字節所用的時間

四、INP(Interaction to Next Paint )

1. 什麼是 INP?

INP:與網頁進行的每次 tapclick 或鍵盤互動的延遲時間

良好的響應速度意味着網頁對互動的響應速度很快。

當網頁響應互動時,瀏覽器會在所繪製的下一幀中提供_視覺反饋。

有些互動自然會比其他互動花費更長的時間,但對於特別複雜的互動,必須快速提供一些初始視覺反饋,讓用户知道正在發生的事情。

INP 的目的不是測量互動的所有最終效果,而是下一次繪製被阻止的時間。通過延遲視覺反饋,用户可能會覺得頁面響應速度不夠快,而 INP 旨在幫助開發者衡量這部分用户體驗。

2. INP

image

3. 良好的 INP 是多少時間?

一般 200 ms 以內

  • INP 低於或等於 200 毫秒表示網頁響應良好
  • INP 高於 200 毫秒且低於或等於 500 毫秒表示網頁的響應能力需要改進
  • INP 高於 500 毫秒表示網頁響應速度很差

在這裏插入圖片描述

4. 什麼是互動?

在這裏插入圖片描述

互動的主要驅動因素通常是 JavaScript,但瀏覽器確實會通過並非由 JavaScript 提供支持的控件(例如複選框、單選按鈕和由 CSS 提供支持的控件)提供互動性。
INP 而言,只觀察以下互動類型

  • 使用鼠標點擊。
  • 點按帶有觸摸屏的設備。
  • 按實體鍵盤或屏幕鍵盤上的某個鍵。

互動發生在主文檔或文檔內嵌的 iframe 中。

系統會在用户離開頁面時計算該頁面的 INP。結果會得到一個能夠代表網頁在其整個生命週期內的整體響應能力的值。INP 較低意味着網頁能夠可靠地響應用户輸入。

5. INP 與 First Input Delay (FID) 有何不同?

INPFirst Input Delay (FID) 的繼任指標。雖然兩者都是響應速度指標,但 FID 僅衡量了網頁上首次互動的輸入延遲。INP 通過觀察網頁上的所有互動來改進 FID,即從輸入延遲開始,到運行事件處理腳本所需的時間,再到瀏覽器繪製下一幀。
這些差異意味着 INPFID 是不同類型的響應能力指標。FID 是用於評估網頁對用户的首次展示的加載響應速度指標,而無論網頁互動在何時發生,INP 都是更可靠的整體響應能力指標。

6. 如果未報告 INP 值,該怎麼辦?

網頁可能不會返回任何 INP 值。導致這種情況的原因可能有很多,其中包括以下原因:

  • 頁面已加載,但用户從未點擊、點按或按鍵盤上的鍵。
  • 網頁已加載,但用户使用不衡量的手勢與網頁互動。
  • 該網頁正被機器人訪問,但該機器人尚未編寫與該網頁交互的腳本。

7. 如何改進 INP?

  • 優化耗時較長的任務
  • 優化輸入延遲
  • 腳本評估和耗時較長的任務
  • 使用 Web Worker 在瀏覽器的主線程之外運行 JavaScript
  • 避免大型、複雜的佈局和佈局抖動
  • 縮小樣式計算的範圍並降低其複雜性

五、 TBT(Total Blocking Time)

1. 什麼是 TBT?

TBT:總阻塞時間,從 FCP 到可交互時間 (TTI) 之間的總時長,其中主線程處於阻塞狀態的時間足夠長,足以阻止輸入響應能力。

每當存在長任務(一種在主線程上運行時間超過 50 毫秒 (ms) 的任務)時,主線程就會被視為阻塞。

我們説主線程處於阻塞狀態,因為瀏覽器無法中斷正在進行的任務。如果用户嘗試在耗時較長的任務過程中與頁面互動,瀏覽器必須等待任務完成才能響應。

如果主線程處於阻塞狀態的時間超過 50 毫秒,用户很可能會注意到延遲,並認為網頁運行緩慢或損壞。

2. 良好的 TBT 是多少時間?

網站的 TBT 應低於 200 毫秒。

TBT 時間(以毫秒為單位) 顏色編碼
0 - 200 綠色(快速)
200-600 橙色(中等)
600 多個 紅色(慢)

3. 如何提高 TBT

  • 將所有工作拆分為運行時間不超過 50 毫秒的代碼塊,並在合適的位置和時間運行這些代碼塊。
  • 降低第三方代碼的影響
  • 縮短 JavaScript 執行時間
  • 去除不必要的 JS 加載、解析、執行
  • 儘量減少主線程工作
  • 儘量減少請求數量,減少傳輸大小

六、 CLS(Cumulative Layout Shift)

1. 什麼是 CLS

CLS:從頁面開始加載到其生命週期狀態更改為隱藏期間發生的所有意外佈局偏移的累計得分。

每當可見元素的位置從渲染的幀更改為下一幀時,都會發生布局偏移。

1.1. 什麼是佈局偏移

佈局偏移由 Layout Instability API 定義。

只要窗口內可見的元素在兩幀之間更改起始位置,該 API 就會報告 layout-shift 。此類元素被視為不穩定元素。

image

1.2. CLS

當資源以異步方式加載或 DOM 元素被動態添加到頁面的現有內容之前,頁面內容通常會發生意外移動。

佈局偏移的原因可能包括尺寸未知的圖片或視頻、呈現的字體大於或小於其初始後備值,或者第三方廣告或微件會自行調整大小。

由於網站在開發過程中的運行情況與其用户的體驗之間的差異,會使此問題變得更糟。例如:

  • 個性化內容或第三方內容在開發和生產環境中的行為通常有所不同。
  • 測試圖片通常已存在於開發者的瀏覽器緩存中,但為最終用户加載所需時間更長。
  • 在本地運行的 API 調用速度通常非常快,以至於開發過程中出現明顯的延遲,在生產環境中可能就會出現嚴重的延遲。

2. 頁面生命週期

在這裏插入圖片描述

3. 良好的 CLS 是多少?

為了提供良好的用户體驗,網站應努力使 CLS 得分不超過 0.1

在這裏插入圖片描述

4. 如何衡量 CLS

  • Chrome 用户體驗報告
  • PageSpeed Insights
  • web-vitals JavaScript
  • Chrome DevTools
  • Lighthouse
  • WebPageTest
  • PerformanceObserver 方法

5. JS 中衡量 CLS

5.1. 簡單示例
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    console.log('Layout shift:', entry);
  }
}).observe({type: 'layout-shift', buffered: true});
5.2. 指標與 API 的區別
  • 如果網頁是在後台加載的,或者在瀏覽器繪製任何內容之前在後台播放,則系統不應報告任何 CLS 值。
  • 如果某個網頁從往返緩存中恢復,其 CLS 值應重置為零,因為用户此次體驗是一次不同的網頁訪問。
  • API 不會針對 iframe 中發生的偏移報告 layout-shift ,但該指標會報告這些變化,因為它們會影響網頁的用户體驗。
5.3. 使用 web-vitalsJavaScript 庫衡量 CLS

可以使用 web-vitalsJavaScript 庫來衡量 CLS

import {onCLS} from 'web-vitals';

onCLS(console.log);

onCLS 源碼

6. 如何改善 CLS?

  • 改善沒有尺寸的圖片
  • 給嵌入內容的延遲加載預留空間
  • 動畫:儘量使用 transform 平移動畫、縮放、旋轉/傾斜元素
  • 網絡字體優化

七、TTFB(Time to First Byte)

1. 什麼是 TTFB?

TTFB:網絡使用資源的第一個字節響應用户請求所需的時間。

TTFB 是以下請求階段的總和:

  • 重定向時間
  • Service Worker 啓動時間(如果適用)
  • DNS 查找
  • 連接和 TLS 協商
  • 請求,直到響應的第一個字節到達

縮短連接設置時間和後端的延遲時間有助於降低 TTFB

2. 良好的 TTFB 是多少時間?

大多數網站都應儘量將 TTFB 控制在 0.8 秒以內。

在這裏插入圖片描述

3. 如何衡量 TTFB?

  • Chrome 用户體驗報告
  • web-vitalsJavaScript
  • WebPageTest
  • PerformanceObserver 方法

4. JS 衡量 TTFB

4.1. 簡單示例
new PerformanceObserver((entryList) => {
  const [pageNav] = entryList.getEntriesByType('navigation');

  console.log(`TTFB: ${pageNav.responseStart}`);
}).observe({
  type: 'navigation',
  buffered: true
});

image

4.2. 使用 web-vitalsJavaScript 庫衡量 TTFB

使用 web-vitalsJavaScript 庫也可以在瀏覽器中以較低的複雜性測量 TTFB

import {onTTFB} from 'web-vitals';

onTTFB(console.log);

onTTFB 源碼

5. 如何優化 TTFB?

  • 具體的項目平台
  • 託管服務商
  • CDN
  • 儘可能的使用緩存
  • 避免多次重定向
  • 使用 service worker

八、FID(First Input Delay)

1. 什麼是 FID?

FID:從用户首次與網頁互動到瀏覽器實際能夠開始處理事件處理腳本以響應相應互動的時間。

2. 良好的 FID 是多少時間?

為了提供良好的用户體驗,網站應努力將 FID 控制在 100 毫秒以內

在這裏插入圖片描述

3. 如何衡量 FID?

FID 指標只能在實際操作衡量,因為它需要真實用户的網頁互動

  • Chrome 用户體驗報告
  • PageSpeed Insights
  • web-vitals JavaScript
  • PerformanceObserver

4. 衡量 JS 中的 FID

4.1. 簡單示例
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    const delay = entry.processingStart - entry.startTime;
    console.log('FID candidate:', delay, entry);
  }
}).observe({type: 'first-input', buffered: true});

image

4.2. 使用 web-vitals JavaScript 庫來衡量 FID
import {onFID} from 'web-vitals';

onFID(console.log);

onFID 源碼

5. 如何優化 FID?

  • 拆分長任務
  • 使用 web worker
  • 縮短 JS 執行時間
  • 減少多餘的 JS
  • 針對具體的情況優化頁面

九、總結

  • 本文整體的概括了以用户為中心的性能衡量指標
  • 也對每個指標進行了具體的描述和提出優化方案
  • 希望對大家有幫助

參考

  • Web Vitals
  • Web Metrics
user avatar hard_heart_603dd717240e2 Avatar yangxiansheng_5a1b9b93a3a44 Avatar DolphinScheduler Avatar zhuchenxi113 Avatar suporka Avatar kalii Avatar delia_5a38831addb7b Avatar fsjohnhuang Avatar webshijie Avatar dushigemi Avatar papermoon Avatar syfssb Avatar
Favorites 14 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.