本文是译文,关注Web Vitals Metrics,翻译系列文章中的01篇
原文连接: Largest Contentful Paint (LCP)
一直以来,对开发者来讲衡量页面加载中主要内容加载、显示的速度都比较困难。因为Load和DOMContentLoaded跟屏幕上用户所见内容并没有必然的关系,因此不够好(它们不是面向用户的指标)。FCP(First Contentful Paint)是基于用户维度的指标,但只关注页面加载的最初阶段,若是页面上存在闪现或者loading组件,也没法反映出用户关注的主要内容是什么时候加载的。后来咱们推荐使用FMP和SI(LightHouse6个指标之一),实际上它们也是复杂的、模糊的,甚至是错误的,并不能准确识别页面主要内容的加载时机。简单为王,研究后发现:javascript
页面加载阶段最重要的内容每每是页面渲染区域最大的那部份内容。
什么是LCP?LCP反映的是从页面开始加载到页面视口上最大的图片或者文本块渲染的时间。LCP<2.5s意味着得分是GOOD。css
哪些元素多是LC的候选人呢?<img>
、svg
中的<image>、<video>
、含有用url()
设置背景图的元素、含文本节点或者内联子元素的块级元素。
故意在一开始设定元素集合是为了简化讨论,后续随着研究的进展,也会不断添加好比:<svg>
和<video>
。java
LCP元素的大小是指视口上可见元素的大小(不包含超过视口元素的大小、发生剪裁的元素、不可见的元素)。对于改变了固有大小的图片来讲,大小要么是图片可见的大小、要么是固有的大小。例如:缩小的图片的大小只计算其显示的大小,而放大的图片的大小,只计算其固有的大小。对于文本元素来讲,只会计算其文本节点的大小。对于全部的元素来讲,都不将css中设置的margin、padding和border计算在内。web
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元素。安全
咱们把分析工具分为: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);
此时就须要用到定制指标的 Element Timing API了。此处不作分析。
后续章节将针对性的给出优化方案。影响LCP的四个方面包括了:
(1)请求阶段缓慢的服务端响应;
(2)渲染阶段阻塞的JS和CSS;
(3)资源加载时间;
(4)客户端渲染。
如何优化LCP,请参阅优化LCP。其它能够提高LCP的优化指南,能够参阅:
1.优化关键渲染路径
2.优化CSS
3.优化JavaScript
4.优化图片
5.优化字体
6.PRPL模式使用