1. 程式人生 > 其它 >前端頁面效能指標

前端頁面效能指標

基本指標介紹

1. 首次繪製(First Paint,FP)

FP 是時間線上的第一個“時間點”,是指瀏覽器從響應使用者輸入網址地址,到瀏覽器開始顯示內容的時間,簡而言之就是瀏覽器第一次發生變化的時間。

2. 首次內容繪製(First Contentful Paint,FCP)

FCP(全稱“First Contentful Paint”,翻譯為“首次內容繪製”),是指瀏覽器從響應使用者輸入網路地址,在頁面首次繪製文字,圖片(包括背景圖)、非白色的 canvas 或者 SVG 才算做 FCP,有些文章說 FCP 是首屏渲染事件,這其實是不對的。

3. 可互動時間(Time to Interactive,TTI)

TTI,翻譯為“可互動時間”表示網頁第一次完全達到可互動狀態的時間點。可互動狀態指的是頁面上的 UI 元件是可以互動的(可以響應按鈕的點選或在文字框輸入文字等),不僅如此,此時主執行緒已經達到“流暢”的程度,主執行緒的任務均不超過 50 毫秒。在一般的管理系統中,TTI 是一個很重要的指標。

4. 最大內容繪製(Largest Contentful Paint,LCP)

LCP(全稱“Largest Contentful Paint”)表示可視區“內容”最大的可見元素開始出現在螢幕上的時間點。

5. 首次有效繪製(First Meaning Paint, FMP) 廢棄

FMP(全稱“First Meaningful Paint”,翻譯為“首次有效繪製”表示頁面的“主要內容”開始出現在螢幕上的時間點,它以前是我們測量使用者載入體驗的主要指標。本質上是通過一個演算法來猜測某個時間點可能是 FMP,但是最好的情況也只有 77%的準確率,在 lighthouse6.0 的時候廢棄掉了這個指標,取而代之的是 LCP 這個指標。

performance 介紹

performance 物件是專門用來用於效能監控的物件,內建了一些前端需要的效能引數。

1. performance.now()方法

performance.now() 返回 performance.navigationStart 至當前的毫秒數。performance.navigationStart 是下文將介紹到的可以說是瀏覽器訪問最初的時間測量點。

performance.now(); // 24614164.599999994

2. performance.timing

3. performance.getEntries()方法

瀏覽器獲取網頁時,會對網頁中每一個物件(指令碼檔案、樣式表、圖片檔案等等)發出一個 HTTP/HTTPS

請求。performance.getEntries() 方法以陣列形式,返回一個 PerformanceEntry 列表,這些請求的時間統計資訊,有多少個請求,返回陣列就會有多少個成員。

指標計算方法

1. 首屏和白屏

白屏時間是指瀏覽器從響應使用者輸入網址地址,到瀏覽器開始顯示內容的時間,一種比較簡單的做法是在 body 標籤之前獲取當前時間 - performance.timing.navigationStart,或者直接獲取 performance 中關於 paint 的兩個資料,都可以直接作為白屏資料,這兩個資料一般差別不大。

首次繪製 FP 包括了任何使用者自定義的背景繪製,它是首先將畫素繪製到螢幕的時刻。

首次內容繪製 FCP 是瀏覽器將第一個 DOM 渲染到螢幕的時間。該指標報告了瀏覽器首次呈現任何文字、影象、畫布或者 SVG 的時間。

也可以使用其他的計算方法:白屏時間 = 頁面開始展示的時間點 - 開始請求的時間點。

2. TTI

關於 TTI 可以首先了解下谷歌提出的效能模型 RAIL:

  1. 響應:輸入延遲時間(從點按到繪製)小於 100 毫秒。使用者點按按鈕(例如開啟導航)。
  1. 動畫:每個幀的工作(從 JS 到繪製)完成時間小於 16 毫秒。使用者滾動頁面,拖動手指(例如,開啟選單)或看到動畫。拖動時,應用的響應與手指位置有關(例如,拉動重新整理、滑動輪播)。此指標僅適用於拖動的持續階段,不適用於開始階段。
  1. 空閒:主執行緒 JS 工作分成不大於 50 毫秒的塊。使用者沒有與頁面互動,但主執行緒應足夠用於處理下一個使用者輸入。
  1. 載入:頁面可以在 1000 毫秒內就緒。使用者載入頁面並看到關鍵路徑內容。

我們可以通過 domContentLoadedEventEnd 來粗略的進行估算:

TTI:domContentLoadedEventEnd - navigationStart

谷歌實驗室也提供了更加便捷準確的 api 包進行測算 tti-polyfil:

import ttiPolyfill from "./path/to/tti-polyfill.js";
ttiPolyfill.getFirstConsistentlyInteractive(opts).then((tti) => {
  // Use `tti` value in some way.
});

3. LCP

在過去,我們也有推薦的效能指標,如:FMP (First Meaningful Paint)SI (Speed Index)可以幫我們捕獲更多的首次渲染之後的載入效能,但這些過於複雜,而且很難解釋,也經常出錯,沒辦法確定主要內容什麼時候載入完。

根據 W3C Web 效能工作組的討論和 Google 的研究,發現度量頁面主要內容的可見時間有一種更精準且簡單的方法是檢視 “繪製面積” 最大的元素何時開始渲染。

所謂繪製面積可以理解為每個元素在螢幕上的 “佔地面積” ,如果元素延伸到螢幕外,或者元素被裁切了一部分,被裁切的部分不算入在內,只有真正顯示在螢幕裡的才算數。圖片元素的面積計算方式稍微有點不同,因為可以通過 CSS 將圖片擴大或縮小顯示,也就是說,圖片有兩個面積:“渲染面積”與“真實面積”。在 LCP 的計算中,圖片的繪製面積將獲取較小的數值。例如:當“渲染面積”小於“真實面積”時,“繪製面積”為“渲染面積”,反之亦然。

頁面在載入過程中,是線性的,元素是一個一個渲染到螢幕上的,而不是一瞬間全渲染到螢幕上,所以“渲染面積”最大的元素隨時在發生變化。如果使用 PerformanceObserver 去捕獲 LCP,會發現每當出現“渲染面積”更大的元素,就會捕獲出一條新的效能條目。

如果元素被刪除,LCP 演算法將不再考慮該元素,如果被刪除的元素剛好是 “繪製面積” 最大的元素,則使用新的 “繪製面積” 最大的元素建立一個新的效能條目。

該過程將持續到使用者第一次滾動頁面或第一次使用者輸入(滑鼠點選,鍵盤按鍵等),也就是說,一旦使用者與頁面開始產生互動,則停止報告新的效能條目。

可以直接使用 PerformanceObserver 來捕獲 LCP:

const observer = new PerformanceObserver((entryList) => {
  const entries = entryList.getEntries();
  const lastEntry = entries[entries.length - 1];
  const lcp = lastEntry.renderTime || lastEntry.loadTime;
  console.log("LCP:", lcp);
});
observer.observe({ entryTypes: ["largest-contentful-paint"] });

LCP 也不是完美的,也很容易出錯,它會在使用者進行互動後就停止捕獲,可能會獲取到錯誤的結果,如果有佔據頁面很大的輪播圖也會產生問題會不斷的更新 LCP

LCP 也有現成的計算工具庫 web-vitals:

import { getLCP } from "web-vitals";

// Measure and log the current LCP value,
// any time it's ready to be reported.
getLCP(console.log);