前端岗位内推来了
本文结合Google官方工具 Lighthouse 分析最新的前端页面性能评分标准,帮助大家更好地理解各种性能指标,以改进和优化相关前端项目。
前端页面性能一直是大家持续关注的话题,因为用户留存率与页面加载性能密切相关。根据Google的数据统计,当页面访问时长从1秒增加到3秒时,用户跳出率会增加32%。
评估前端页面性能通常有两种形式:一是使用性能分析工具在线对各项指标进行评分和评估;二是使用性能监控,通过 Performance API 或自定义跟踪点报告用户的真实网络访问情况,然后进行统计分析。
虽然统计收集用户数据更贴近实际,但为了对页面性能评估有一个统一的量化标准,我们通常选择使用标准评分工具来评估页面性能。
在性能分析的早期阶段,我们会使用Chrome开发者工具分析网页,包括查看 load
和DOMContentLoaded
等事件触发的时间。后来出现了一系列性能分析工具,如Webpage Analyzer、WebPageTest、YSlow等。
现在Google已经正式将其自主开发的Lighthouse嵌入到开发者工具标签中,我们将Lighthouse视为标准评估工具。
Lighthouse 是一个开源的网页性能分析工具,提供了关于页面最佳实践的相关建议。除了可以直接在Chrome DevTools中使用外,它还支持浏览器扩展(Chrome和Firefox)或npm包(Node API或CLI)。
像 Google 的 Web measure 和 PageSpeed Insight等工具都使用Lighthouse来分析页面。
1.Lighthouse 的迭代和性能指标变化
Lighthouse 的第一个开源版本可以追溯到2016年,截至2020年10月,最新版本是6.4.1,总共经历了89次迭代。多年来,Lighthouse一直在更新其性能指标的选择。
在最新的6.x版本中,与5.x版本相比,Google引入了三个新的性能指标:移除了FMP(First Meaningful Paint)、FCI(First CPU Idle)和 mpFID(Max Potential First Input Delay);
添加了TBT(Total Blocking Time)、LCP(Largest Contentful Paint)和CLS(Cumulative Layout Shift)。以下部分将对这些指标进行详细解释。
2.如何计算页面性能得分
如下图所示,在页面性能部分,Lighthouse将评估6个关键指标的性能,并计算页面的性能得分。
根据最新的6.x计算方法,每个性能指标对应一个分数。例如,在上图中,FCP、SI、LCP、TTI、TBT和CLS的值分别对应78、62、37、5、99和92的单项得分。通常来说,指标值越小,其对应的得分越高。
这六个指标分别被赋予15%、15%、25%、15%、25%和5%的权重。总体性能得分的计算如图所示 — 通过加权平均得到总分60分。
每个指标值如何对应其各自的得分计算方法的具体细节可以在文章末尾的参考文献5和6中找到。
在Lighthouse v6.0版本中, 移除了三个关键性能指标: FMP(First Meaningful Paint)、FCI(First CPU Idle) 和 mpFID(Maximum Potential First Input Delay)。
我们将首先examine这三个已弃用指标的定义,以better理解当前版本如何选择其指标。
1. 什么是FMP,它与FCP有什么区别?
谈到FMP,我们必须首先介绍First Contentful Paint (FCP):第一次内容渲染的时间。
顾名思义,只要浏览器第一次触发The First Page Paint事件,这一刻就是FCP。然而,此时渲染的内容不一定是重要的页面信息,比如只绘制了一个头部操作栏或甚至可见元素。虽然它在Lighthouse 6.0中被保留,但其在性能得分中的权重从23%降至15%。
因此,从用户的角度来看,FCP不能作为页面性能的准确指标。
在这种背景下,FMP(First Meaningful Paint)应运而生。根据官方定义,FMP指的是自页面加载开始以来,初始屏幕上大部分或主要内容已被渲染的时间点。
那么FMP的计时如何确认?让我们先看最基本的计算方法:
我们首先计算布局对象的数量(使用LayoutAnalyzer进行测试计算;参见参考文献17)。
如下图所示,可以看到页面加载过程是布局对象逐步进入布局树并渲染的过程。
layoutAnalyzer 收集布局对象的数量,有一个计数器叫 LayoutObjectsThatHadNeverHadLayout
,代表新增加的布局对象的数量。
通过测试发现,与其他计数器相比,它变化最大的时刻往往是页面上最重要的元素被渲染的时候。
因此,FMP指标的计算方法是LayoutObjectsThatHadNeverHadLayout(新增布局对象)经历最大变化后的下一刻(跟随最大布局变化的绘制)。
当然,也有一些情况下上述情况不适用:
a) 如果页面很长,可能在第一屏内添加的不可见布局对象比可见的多。在这种情况下,FMP变得不准确。
b) 在加载网络字体的情况下,文本使用fallback字体进行布局但默认在loadstart后3秒内不绘制;这也会影响FMP的计算。
对于场景1,FMP引入了"布局重要性"的概念来解决这个问题;对于场景2,FMP延迟统计以使指标更准确地反映页面状况。更详细的解决方案请参考参考文献18。
然而,FMP最终在6.0版本中被弃用,主要是由于以下两个原因:
在生产环境中,FMP对页面上的微小变化过于敏感,容易导致结果不一致。
这个指标的定义过于依赖浏览器的具体实现细节,缺乏标准化的参考。
2.LCP的到来取代了FMP
前一节提到了FCP和FMP的缺点,所以W3C的性能组一直在思考找到一个合适的指标,更准确地反映用户看到页面主要内容的时间。
有时候更简单更好。基于各方面关于页面性能的讨论,终于找到了一个更准确的方法来衡量页面的主要内容是否已加载,这就是 LCP(Largest Contentful Paint)
。
LCP指的是视口内最大内容元素渲染的时间。这个指标在Lighthouse 6.0中正式引入,在最终性能得分中占据高达25%的权重。
LCP 应该是除FCP之外最容易定义的指标之一。从其定义来看,有两个关键点:选择哪些元素进行比较,以及如何确定它们的大小。
根据官方文档,以下元素将被视为 Largest Contentful Element 的一部分:
<img>
<svg>
中的<image>
<video>
通过url()函数加载背景图片的元素
包含文本节点或内联文本子元素的块级元素
我们如何确定一个元素的大小?主要基于这四条规则:
视口内可见元素的大小;如果它们超出或被裁剪或被遮挡,则不计入元素大小。
对于图像元素,大小由Min(实际大小,原始大小)决定。
对于文本元素,只考虑覆盖所有文本的最小矩形区域。
对于所有元素,不包括margin、padding、border等在计算中。
Google对这个指标的评价如下:LCP是一个非常重要的以用户为中心的指标;它反映了用户层面感知的加载速度;它标志着主要内容中最大内容元素的加载完成;LCP时间越短,用户感知页面可用的速度越快。
3.被放弃的FCI是什么,为什么它与TTI如此密切相关?
FCI(First CPU Idle:首次CPU空闲),这个指标用来衡量一个页面达到最小可交互标准需要多长时间。
最小可交互性的确认需要同时满足以下两个条件:
a) 屏幕上的大多数UI元素是可交互的
b) 页面对用户输入的响应平均在合理范围内
TTI(Time To Interactive:页面可交互时间),指页面达到完全可交互状态所需的时间。
完全可交互意味着同时满足以下三个条件:
a) FCP之后,页面上已经渲染了有用的内容
b) 为最可见的页面元素注册了事件回调
c) 页面对用户交互的响应在50ms以内
2017年,First Interactive 指标被分为两个指标: First Interactive 和 Consistently Interactive; 次年7月, First Interactive被重命名为 FCI,而Consistently Interactive 被重命名为TTI。可以看出,FCI和TTI是两个反映用户交互响应的指标。
那么,最小可交互性和完全可交互性是如何计算的?在介绍具体计算方法之前,我们需要知道,这两个指标都是模糊的,可以在不同情况下不断优化和改进。
FCI的最小可交互时间
在主线程的时间线上,从FMP开始直到某个任务结束之后,找到一个长度为f(t)的时间窗口W。如果W满足在其持续时间内任何时刻都没有连续超过250ms的任务集,并且在其结束前后1秒内没有长任务(JS执行时间超过50ms的任务)。那个任务结束的时刻就是我们定义的FCI。其中f(t)=4e^(-0.045t)+1
。
下图中红框指示的时间点就是FCI。
TTI完全可交互时间
从网络和主线程的时间线上,找到第一个5s窗口期 W。在 W 期间,应满足以下条件:任何时刻并发网络请求不超过两个,且没有超过50ms的长任务。W 之前最后一个长任务结束的时间就是我们所说的TTI。
下图中红框指示的时间点就是TTI:
尽管有人指出FCI在某些时候比TTI更有意义,但它们之间的区别仍然不足以证明 Lighthouse 保留两个相似的指标。
因此,在Lighthouse 6.0中,最终决定使用TTI代替FCI。
4.mpFID和新增的TBT指标
mpFID(max potential First Input Delay)指的是页面上从用户输入到实际开始处理事件回调的潜在最大延迟时间。
mpFID的具体计算方法是选择从FCP到TTI之间JavaScript执行时间最长的任务,然后从该任务消耗的时间中减去50ms。
然而,mpFID只代表一个最大延迟时间,可能与用户实际体验到的延迟时间不同。用户在不同时间获得的FID也会有所不同。因此,mpFID并不能真实反映页面对用户输入的响应时间。
在5.x版本计算性能得分时,mpFID权重为0,不参与打分。虽然这个指标不再出现在报告中,但它仍然保留在JSON数据中,仍然是官方认可的关键用户体验指标。
那么,TBT(Total Blocking Time)到底是什么,为什么在性能报告中选择它而不是FID呢?
我们先来看看它的定义:TBT指的是页面在响应用户输入时被阻塞的总累计时间。
具体计算方法相当清晰 — 将FCP和TTI之间的所有长任务加起来,并将它们的阻塞部分的时间相加,就得到了TBT。阻塞部分的时间指的是长任务执行超过50ms的任何部分;例如,如果一个长任务总共花费70ms,那么阻塞时间就是20ms。
可以看出,与mpFID相比,TBT是一个更稳定的指标,能更准确地反映页面对用户输入的平均延迟响应。
5. 新增的CLS
CLS(Cumulative Layout Shift),是用来衡量视觉界面稳定性的指标。
数据来源于Layout Instability API(参见参考文献14),计算方法如下:
layout shift score = impact fraction * distance fraction
布局移动分数 = 影响分数 * 距离分数
其中impact fraction指的是对整个视口的影响程度。例如,在下图中,如果文本占整个视口的50%,在下一帧中相对于上一帧向下移动了25%,那么它影响了整个页面的75%。因此,impact fraction为0.75。
distance fraction相对容易理解,它指的是改变的距离占整个视口的比例。例如,在上述案例中,移动25%意味 着distance fraction 为 0.25。
因此,图示demo的CLS值计算为0.75 * 0.25 = 0.1875。
更详细的计算方法可以参考参考文献13和14。
一个说明CLS如何影响用户体验的例子:如下图所示,当用户试图点击取消按钮时,突然页面发生布局偏移,确认按钮出现在之前取消按钮的位置...
可以看出,CLS是一个更加以用户为中心的新性能评估指标。
目前,CLS作为一个新增指标权重较小,只有5%,但Lighthouse已经在考虑在下一个主要版本中增加其权重。
6. 一直存在的Speed Index
Speed Index(SI)用于衡量可见内容填充页面的速度,计算过程使用开源工具Speedline(参考文献16)。
Speedline记录页面的视频,并通过测量第一帧和最后一帧之间的时间差来计算Speed Index的值。
值得一提的是,SI的最终得分将通过与数据库中真实网站的SI值进行比较来计算。目前,SI得分和评分标准如下表所示:
回顾上述指标替换的过程,我们可以看到,无论是从FMP到LCP,FCI到TTI,还是FID到TBT,目前在性能指标的选择上,都在向更稳定的方向发展:指标的定义越来越简洁明了,计算方法也趋向标准化。
然而,我们也应该知道,这里没有银弹;每个指标都会有其局限性。在许多场景下,低分并不一定意味着页面体验差。只有理解这些指标背后的原理,我们才能基于性能得分更科学地评估页面。
由于性能相关技术的快速迭代,如果本文有任何遗漏,欢迎交流和纠正。
最后:
CSS技巧与案例详解
vue2与vue3技巧合集
VueUse源码解读