本文是译文,关注Web Vitals Metrics,翻译系列文章中的01篇
原文链接:Largest Contentful Paint (LCP)
前言
一直以来,对开发者来说衡量页面加载中主要内容加载、显示的速度都比较困难。由于Load和DOMContentLoaded跟屏幕上用户所见内容并无必然的关系,所以不够好(它们不是面向用户的指标)。FCP(First Contentful Paint)是基于用户维度的指标,但只关注页面加载的最初阶段,如果页面上存在闪现或者loading组件,也无法反映出用户关注的主要内容是何时加载的。后来我们推荐使用FMP和SI(LightHouse6个指标之一),实际上它们也是复杂的、模糊的,甚至是错误的,并不能准确识别页面主要内容的加载时机。简单为王,研究后发现:
页面加载阶段最重要的内容往往是页面渲染区域最大的那部分内容。
1 LCP定义和标准
什么是LCP?LCP反映的是从页面开始加载到页面视口上最大的图片或者文本块渲染的时间。LCP<2.5s意味着得分是GOOD。
1.1 LCP中的Contentful元素包含哪些?
哪些元素可能是LC的候选人呢?<img>
、svg
中的<image>、<video>
、含有用url()
设置背景图的元素、含文本节点或者内联子元素的块级元素。
故意在一开始设定元素集合是为了简化讨论,后续随着研究的进展,也会不断添加比如:<svg>
和<video>
。
1.2 元素大小如何衡量?
LCP元素的大小是指视口上可见元素的大小(不包含超过视口元素的大小、发生剪裁的元素、不可见的元素)。对于改变了固有大小的图片来说,大小要么是图片可见的大小、要么是固有的大小。例如:缩小的图片的大小只计算其显示的大小,而放大的图片的大小,只计算其固有的大小。对于文本元素来说,只会计算其文本节点的大小。对于所有的元素来说,都不将css中设置的margin、padding和border计算在内。
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工具
Chrome User Experience Report
PageSpeed Insights
Search Consol
JS lib: web-vitals
Lab工具
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模式使用
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。