前端性能指標:Largest Contentful Paint

本文是譯文,關注Web Vitals Metrics,翻譯系列文章中的01篇
原文連接: Largest Contentful Paint (LCP)

前言

一直以來,對開發者來講衡量頁面加載中主要內容加載、顯示的速度都比較困難。因爲Load和DOMContentLoaded跟屏幕上用戶所見內容並沒有必然的關係,因此不夠好(它們不是面向用戶的指標)。FCP(First Contentful Paint)是基於用戶維度的指標,但只關注頁面加載的最初階段,若是頁面上存在閃現或者loading組件,也沒法反映出用戶關注的主要內容是什麼時候加載的。後來咱們推薦使用FMP和SI(LightHouse6個指標之一),實際上它們也是複雜的、模糊的,甚至是錯誤的,並不能準確識別頁面主要內容的加載時機。簡單爲王,研究後發現:javascript

頁面加載階段最重要的內容每每是頁面渲染區域最大的那部份內容。

1 LCP定義和標準

什麼是LCP?LCP反映的是從頁面開始加載到頁面視口上最大的圖片或者文本塊渲染的時間。LCP<2.5s意味着得分是GOOD
css

1.1 LCP中的Contentful元素包含哪些?

哪些元素多是LC的候選人呢?<img>svg中的<image>、<video>、含有用url()設置背景圖的元素、含文本節點或者內聯子元素的塊級元素
故意在一開始設定元素集合是爲了簡化討論,後續隨着研究的進展,也會不斷添加好比:<svg><video>java

1.2 元素大小如何衡量?

LCP元素的大小是指視口上可見元素的大小(不包含超過視口元素的大小、發生剪裁的元素、不可見的元素)。對於改變了固有大小的圖片來講,大小要麼是圖片可見的大小、要麼是固有的大小。例如:縮小的圖片的大小隻計算其顯示的大小,而放大的圖片的大小,只計算其固有的大小。對於文本元素來講,只會計算其文本節點的大小。對於全部的元素來講,都不將css中設置的margin、padding和border計算在內。web

1.3 什麼時候發生LCP?(關於它的細節)

web頁面加載是分步進行的,所以,LC會發生改變。爲了應對這種狀況,瀏覽器分發了一個類型爲largest-contentful-paint的PerformanceEntry,用於當瀏覽器繪製了第一幀時識別LC元素。以後,當渲染後續的幀時,只要LC元素髮生變化,瀏覽器又會分發其它的PerformanceEntry
例如:頁面中存在文本和hero圖片,一開始瀏覽器可能渲染的是文本,此時瀏覽器就會分發一個其element引用指向<p>或者<h1>的PerformanceEntry;以後,一旦hero圖片完成加載,瀏覽器又會分發一個element引用指向<img>的類型爲largest-contentful-paint的Entry。跨域


LC元素只能是已經渲染了的可見元素,所以,剛開始可能會有其餘的小一點的元素被檢測爲LC元素,但只要更大的元素渲染完成,就會經過PerformanceEntry對象更新成爲最新的。已經被檢測爲LC的元素若是從視口中移除了,只要沒有更大的元素渲染,它就一直是LC元素。當用戶與頁面進行交互之後,瀏覽器就中止分發新的Entry。瀏覽器


加載時間和渲染時間:基於安全考慮,缺失Timing-Allow-Origin響應頭的圖片的渲染時間戳將不會給暴露給跨域圖片。只會暴露其渲染時間。下面例子展現的是渲染時間沒法得到的元素處理狀況。咱們推薦儘可能加上Timing-Allow-Origin響應頭以使結果更加精確。緩存


除了上述的LC元素的出現時間不肯定,元素的佈局和大小也會發生變化。爲了下降計算和分發PerformanceEntry帶來的性能損耗,元素大小或者位置的變化不會產生新的LC候選元素,只會考慮視口上元素的初始大小和位置。這也就意味着那些初始階段不渲染在屏幕上,以後又渲染出來的圖像將不會被標記檢測。這也意味着那些初始加載在視口上以後又再也不顯示的元素仍然會標記其初始在視口上的大小。
例子:

上述圖中兩條時間線裏面,LC元素都發生了變化。第一個例子一開始最大的LC被隨後出現的較大LC比下去了;第二個例子,以前最大的LC不存在了,被新的取代。
頁面加載過程當中後面加載的內容比以前的大的狀況很常見,下面的圖展現了頁面加載完成以前LCP的狀況。

第一個例子:logo加載較早,即便其它元素逐漸加載它一直保持着是LC元素。第二個例子:在圖片、logo加載徹底以前,文本段落是LC元素。因爲單個圖片依然比段落小,整個加載過程它一直是LC元素。安全

3 測量LCP的工具備哪些?

咱們把分析工具分爲:Field現場工具和Lab開發工具。
Field工具app

Chrome User Experience Report
PageSpeed Insights
Search Consol
JS lib: web-vitals

Lab工具ide

Chrome DevTool
LightHouse
WebPageTest

JavaScript
(1)Largest Contentful Paint API + PerformanceObserver

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

代碼中的例子對每一個LCP候選人都log出來了。通常來講,最終entry 的startTime即爲LCP,但也存在例外的一些狀況。好比:後臺tab頁、前進後退緩存、iframe中的LCP會被忽略等狀況。
(2)利用開發好的Javascript庫,能夠幫助咱們屏蔽這些細節,用法以下:

import {getLCP} from 'web-vitals';
// Measure and log LCP as soon as it's available.
getLCP(console.log);

4 若是最大元素並不是最重要的當如何?

此時就須要用到定製指標的 Element Timing API了。此處不作分析。

5 影響LCP的四個因素,

後續章節將針對性的給出優化方案。影響LCP的四個方面包括了:
(1)請求階段緩慢的服務端響應;
(2)渲染階段阻塞的JS和CSS;
(3)資源加載時間;
(4)客戶端渲染。

如何優化LCP,請參閱優化LCP。其它能夠提高LCP的優化指南,能夠參閱:
1.優化關鍵渲染路徑
2.優化CSS
3.優化JavaScript
4.優化圖片
5.優化字體
6.PRPL模式使用

相關文章
相關標籤/搜索