Blog
Blog copied to clipboard
Largest Contentful Paint (LCP)
Largest Contentful Paint (LCP)
LCP 全称 “Largest Contentful Paint”,翻译为“最大内容绘制”,用于监控网页可视区内“绘制面积”最大的元素开始呈现在屏幕上的时间点。
1. 介绍
度量网页 “主要内容” 何时呈现在用户眼里是一项非常具有挑战的事情。
历史上一直如此,最早期使用 load
与 DOMContentLoaded
,但它俩无法度量内容何时渲染,“主要内容”何时呈现在用户眼里更无法度量,特别是单页应用流行起来之后,这两个度量标准更无参考价值。
后面使用 First Paint
与 First Contentful Paint
,但它俩更多的是专注于“初始渲染”,不会考虑绘制内容的重要性。如果页面一开始显示一个小菊花(Loading Indicator),此时此刻这个被捕获的时间点所呈现给用户的内容并不是有价值的主要内容。
使用比较高级的 First Meaningful Paint
与 Speed Index
可以度量主要内容何时呈现在用户眼里,但它俩的捕获原理比较复杂,所以经常出错,FMP在最佳情况下的准确率也只有77%。
关于FMP的捕获原理可以查看文章 《捕获FMP的原理》
随着不断研究,前不久一种新的度量标准诞生了,也就是本文介绍的对象LCP。
2. LCP
根据W3C Web性能工作组的讨论和Google的研究,发现度量页面主要内容的可见时间有一种更精准且简单的方法是查看 “绘制面积” 最大的元素何时开始渲染。
所谓绘制面积可以理解为每个元素在屏幕上的 “占地面积”,如果元素延伸到屏幕外,或者元素被裁切了一部分,被裁切的部分不算入在内,只有真正显示在屏幕里的才算数。
图片元素的面积计算方式稍微有点不同,因为可以通过CSS将图片扩大或缩小显示,也就是说,图片有两个面积:“渲染面积”与“真实面积”。在LCP的计算中,图片的绘制面积将获取较小的数值。例如:当“渲染面积”小于“真实面积”时,“绘制面积”为“渲染面积”,反之亦然。
页面在加载过程中,是线性的,元素是一个一个渲染到屏幕上的,而不是一瞬间全渲染到屏幕上,所以“渲染面积”最大的元素随时在发生变化。如果使用 PerformanceObserver
去捕获LCP,会发现每当出现“渲染面积”更大的元素,就会捕获出一条新的性能条目。
如果元素被删除,LCP算法将不再考虑该元素,如果被删除的元素刚好是 “绘制面积” 最大的元素,则使用新的 “绘制面积” 最大的元素创建一个新的性能条目。
该过程将持续到用户第一次滚动页面或第一次用户输入(鼠标点击,键盘按键等),也就是说,一旦用户与页面开始产生交互,则停止报告新的性能条目。
所以应该仅向分析服务器发送最后捕获出的那个性能条目。
图中绿色蒙层代表“绘制面积”最大的元素,可以看出,随着页面不断加载,“绘制面积”最大的元素在不停的变化。
3. 限制
LCP也不是完美的,也很容易出错,它具有如下问题:
- 该算法在检查到用户与页面产生交互时停止,也就是说,如果在“主要内容”显示之前发生了“用户输入”,算法将不会捕获到主要内容。如果用户很早就开始与网页产生交互,该算法将会捕获错误的结果或者没有结果。
- 由于元素一旦删除就不能被视为是面积最大,所以在具有大图片轮播的页面中会出现问题。如果在绘制下一张图时,当前图片被删除,并且下一张图被认为是面积最大,那么算法将基于轮播图不断更新LCP。
元素被删除后不能被认为是面积最大主要是解决“启动画面”问题。
4. Example
使用 PerformanceObserver
捕获LCP非常简单,仅需设置entryType
为 largest-contentful-paint
即可。
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较为理解与推理,而且Google也出了web-vitals库获取LCP值。但是PerformanceObserver API在Native容器中兼容性基本为0,请问这种情况下LCP还能作为核心的T2体感时间指标吗?
另外我也有个问题,对于单页应用是否只需要关注页面首次加载,而不用关注前端路由切换的 LCP 呢?