基本指標介紹
首次繪制(First Paint,FP)
FP 是時間線上的第一個“時間點”,是指瀏覽器從響應用戶輸入網址地址,到瀏覽器開始顯示內容的時間,簡而言之就是瀏覽器第一次發生變化的時間。
首次內容繪制(First Contentful Paint,FCP)
FCP(全稱“First Contentful Paint”,翻譯為“首次內容繪制”),是指瀏覽器從響應用戶輸入網絡地址,在頁面首次繪制文本,圖片(包括背景圖)、非白色的 canvas 或者 SVG 才算做 FCP,有些文章說 FCP 是首屏渲染事件,這其實是不對的。
可交互時間(Time to Interactive,TTI)
TTI,翻譯為“可交互時間”表示網頁第一次完全達到可交互狀態的時間點。可交互狀態指的是頁面上的 UI 組件是可以交互的(可以響應按鈕的點擊或在文本框輸入文字等),不僅如此,此時主線程已經達到“流暢”的程度,主線程的任務均不超過 50 毫秒。在一般的管理系統中,TTI 是一個很重要的指標。
最大內容繪制(Largest Contentful Paint,LCP)
LCP(全稱“Largest Contentful Paint”)表示可視區“內容”最大的可見元素開始出現在屏幕上的時間點。
首次有效繪制(First Meaning Paint, FMP) 廢棄
FMP(全稱“First Meaningful Paint”,翻譯為“首次有效繪制”表示頁面的“主要內容”開始出現在屏幕上的時間點,它以前是我們測量用戶加載體驗的主要指標。本質上是通過一個算法來猜測某個時間點可能是 FMP,但是最好的情況也只有 77%的准確率,在 lighthouse6.0 的時候廢棄掉了這個指標,取而代之的是 LCP 這個指標。

performance 介紹
performance 對象是專門用來用於性能監控的對象,內置了一些前端需要的性能參數。
performance.now()方法
performance.now()
返回 performance.navigationStart
至當前的毫秒數。performance.navigationStart
是下文將介紹到的可以說是瀏覽器訪問最初的時間測量點。
performance.now(); // 24614164.599999994
performance.timing

performance.getEntries()方法
瀏覽器獲取網頁時,會對網頁中每一個對象(腳本文件、樣式表、圖片文件等等)發出一個 HTTP/HTTPS
請求。performance.getEntries()
方法以數組形式,返回一個 PerformanceEntry
列表,這些請求的時間統計信息,有多少個請求,返回數組就會有多少個成員。

指標計算方法
首屏和白屏
白屏時間是指瀏覽器從響應用戶輸入網址地址,到瀏覽器開始顯示內容的時間,一種比較簡單的做法是在 body
標簽之前獲取當前時間 - performance.timing.navigationStart
,或者直接獲取 performance
中關於 paint
的兩個數據,都可以直接作為白屏數據,這兩個數據一般差別不大。
首次繪制 FP
包括了任何用戶自定義的背景繪制,它是首先將像素繪制到屏幕的時刻。
首次內容繪制 FCP
是瀏覽器將第一個 DOM
渲染到屏幕的時間。該指標報告了瀏覽器首次呈現任何文本、圖像、畫布或者 SVG
的時間。
也可以使用其他的計算方法:白屏時間 = 頁面開始展示的時間點 - 開始請求的時間點。
TTI
關於 TTI 可以首先了解下谷歌提出的性能模型 RAIL:

- 響應:輸入延遲時間(從點按到繪制)小於
100
毫秒。用戶點按按鈕(例如打開導航)。
- 動畫:每個幀的工作(從
JS
到繪制)完成時間小於16
毫秒。用戶滾動頁面,拖動手指(例如,打開菜單)或看到動畫。拖動時,應用的響應與手指位置有關(例如,拉動刷新、滑動輪播)。此指標僅適用於拖動的持續階段,不適用於開始階段。
- 空閑:主線程
JS
工作分成不大於50
毫秒的塊。用戶沒有與頁面交互,但主線程應足夠用於處理下一個用戶輸入。
- 加載:頁面可以在
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.
});
LCP
在過去,我們也有推薦的性能指標,如:FMP (First Meaningful Paint)
和SI (Speed Index)
可以幫我們捕獲更多的首次渲染之后的加載性能,但這些過於復雜,而且很難解釋,也經常出錯,沒辦法確定主要內容什么時候加載完。
根據
W3C Web
性能工作組的討論和
所謂繪制面積可以理解為每個元素在屏幕上的 “占地面積” ,如果元素延伸到屏幕外,或者元素被裁切了一部分,被裁切的部分不算入在內,只有真正顯示在屏幕里的才算數。圖片元素的面積計算方式稍微有點不同,因為可以通過
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);