对于 Web 开发人员来说,如何衡量一个 Web 页面的性能一直是一个难题。
最初,我们使用 Time to First Byte
、DomContentLoaded
和 Load
这些衡量文档加载进度的指标(DOMContentLoaded 在 HTML 文档本解析之后触发,而 load 是在 HTML 所有相关资源被加载完成后触发。),但它们不能直接反应用户视觉体验。
为了能衡量用户视觉体验,Web 标准中定义了一些性能指标,这些性能指标被各大浏览器标准化实现,例如 First Paint 和 First Contentful Paint。还有一些由 Web 孵化器社区组(WICG)提出的性能指标,如 Largest Contentful Paint
、Time to Interactive
、First Input Delay
、First CPU Idle
。另外还有 Google 提出的 First Meaningful Paint
、Speed Index
,百度提出的 First Screen Paint
。
这些指标之间并不是毫无关联,而是在以用户为中心的目标中不断演进出来的,有的已经不再建议使用、有的被各种测试工具实现、有的则可以作为通用标准有各大浏览器提供的可用于在生产环境测量的 API。
RAIL 性能模型
RAIL
是 Response, Animation, Idle, 和 Load的首字母缩写, 是一种由 Google Chrome 团队于 2015 年提出的性能模型, 用于提升浏览器内的用户体验和性能。RAIL 模型的理念是”以用户为中心.
这个名字的由来是四个英文单词的首字母:
响应(Response
):应该尽可能快速的响应用户, 应该在 100ms
以内响应用户输入。
动画(Animation
):从技术上来说,在展示动画的时候,每一帧应该以 16ms
进行渲染(1秒60帧,一帧16.6ms),这样可以保持动画效果的一致性。但是浏览器需要大约 6 毫秒来渲染一帧,所以目标上得在10 毫秒或更短的时间内生成动画的每一帧 。
空闲(Idle
):当执行长任务时,应该把主线程的任务划分到执行时间小于 50ms
的片段中去,这样可以释放线程以进行用户交互。
加载(Load
):根据用户的设备和网络能力优化相关的快速加载性能。目前对于网速快的电脑设备,应该在小于 1s-2s
的时间内加载完成你的网站,并可以进行用户交互。对于首次加载,在使用速度较慢 3G 连接的中端移动设备上,理想的目标是在 5 秒或更短的时间内实现可交互。
LCP最大内容绘制 (Largest Contentful Paint)
LCP(Largest Contentful Paint)最大内容绘制,可视区域
中最大的内容元素
呈现到屏幕上的时间,用以估算页面的主要内容对用户可见时间。
img
元素svg
元素video
元素(封面图)url()
函数加载背景图片的元素文本节点
或其他内联级文本元素子级的块级
元素为了提供良好的用户体验,网站应力争使用 2.5 秒或更短的“最大内容绘画” 。
以下是一些示例:
在以上两个时间轴中,最大的元素随内容加载而变化。在第一个示例中,新内容被添加到DOM中,并且更改了最大的元素。在第二个示例中,布局发生更改,以前最大的内容从视口中删除。
通常情况下,延迟加载的内容要比页面上已有的内容大,但不一定是这种情况。接下来的两个示例显示了在页面完全加载之前发生的最大内容绘画。
在这个示例中,Instagram 徽标相对较早地加载,即使逐渐显示其他内容,它仍然是最大的元素。
在 Instagram 时间轴的第一帧中,您可能会注意到相机徽标周围没有绿色框。那是因为它是一个 svg 元素,并且 svg元素当前不被视为 LCP 候选对象。
在 Google 搜索结果页面示例中,最大的元素是一段文本,该文本在任何图像或徽标加载完成之前显示。由于所有单个图像均小于此段,因此在整个加载过程中,它始终是最大的元素。
LCP时间(秒) | 速度 |
---|---|
0-2.5 | 绿色(快速) |
0-4 | 橙色(中等) |
超过4 | 红色(慢) |
LCP 主要受四个因素影响:
FID 首次输入延迟 (First Input Delay)
FID(First Input Delay)首次输入延迟,从用户第一次与页面交互(例如单击链接、点击按钮等)到浏览器实际能够响应该交互的时间。
输入延迟是因为浏览器的主线程正忙于做其他事情,所以不能响应用户。发生这种情况的一个常见原因是浏览器正忙于解析和执行应用程序加载的大量计算的 JavaScript。
第一次输入延迟通常发生在第一次内容绘制(FCP)和可持续交互时间(TTI)之间,因为页面已经呈现了一些内容,但还不能可靠地交互。
如上图所示,浏览器接收到用户输入操作时,主线程正在忙于执行一个耗时比较长的任务,只有当这个任务执行完成后,浏览器才能响应用户的输入操作。它必须等待的时间就此页面上该用户的 FID 值。
例如,以下所有 HTML 元素都需要在响应用户交互之前等待主线程上正在进行的任务完成:
CLS 累积布局偏移 (Cumulative Layout Shift)
Cumulative Layout Shift(CLS)累计布局偏移,CLS 会测量在页面整个生命周期中发生的每个意外的布局移位的所有单独布局移位分数的总和,它是一种保证页面的视觉稳定性从而提升用户体验的指标方案。
您是否曾经在页面上突然发生变化时在没有警告的情况下,文字移动了,并且您失去了位置。甚至更糟:您将要点击一个链接或一个按钮,但是在手指落下的瞬间,链接移动了,您最终单击了其他东西!
页面内容的意外移动通常是由于异步加载资源或将 DOM 元素动态添加到现有内容上方的页面而发生的。罪魁祸首可能是尺寸未知的图像或视频,呈现比其后备更大或更小的字体,或者是动态调整自身大小的第三方广告或小部件。
CLS时间(秒) | 速度 |
---|---|
0-0.1 | 绿色(快速) |
0.1-0,25 | 橙色(中等) |
超过0,25 | 红色(慢) |
FCP首次内容绘制 (First Contentful Paint)
FCP(First Contentful Paint)首次内容绘制,浏览器首次绘制来自 DOM 的内容的时间,内容必须是文本
、图片
(包含背景图)、非白色的 canvas 或 SVG
,也包括带有正在加载中的 Web 字体的文本
。
这是用户第一次开始看到页面内容,但仅仅有内容,并不意味着它是有用的内容(例如 Header、导航栏等),也不意味着有用户要消费的内容。在第二张图的时候FCP就已经出来来了,它指的是html中的dom渲染完成之后的时间,后续动态创建的不管
FCP时间(秒) | 速度 | (HTTP存档百分位数) |
---|---|---|
0-2 | 绿色(快速) | 75–100 |
2-4 | 橙色(中等) | 50–74 |
超过4 | 红色(慢) | 0–49 |
TTI 可交互时间 (Time to Interactive)
表示网页第一次
完全达到可交互状态 的时间点,浏览器已经可以持续性的响应用户的输入。完全达到可交互状态的时间点是在最后一个长任务(Long Task)完成的时间, 并且在随后的 5 秒内
网络和主线程是空闲
的。
LCP时间(秒) | 速度 |
---|---|
0-2.5 | 绿色(快速) |
0-4 | 橙色(中等) |
超过4 | 红色(慢) |
TBT 总阻塞时间 (Total Blocking Time)
Total Block Time(TBT)总阻塞时间,度量了 FCP 和 TTI 之间的总时间,在该时间范围内,主线程被阻塞足够长的时间以防止输入响应。
只要存在长任务,该主线程就会被视为“阻塞”,该任务在主线程上运行超过50毫秒(ms)。我们说主线程“被阻止”是因为浏览器无法中断正在进行的任务。因此,如果用户确实在较长的任务中间与页面进行交互,则浏览器必须等待任务完成才能响应。
如果任务足够长(例如,超过50毫秒的任何时间),则用户很可能会注意到延迟并感觉页面缓慢或过时。
给定的长任务的阻止时间是其持续时间超过50毫秒。页面的总阻塞时间是FCP和TTI之间发生的每个长任务的阻塞时间的总和。
例如,考虑页面加载期间浏览器主线程的下图:
上面的时间轴有五个任务,其中三个是长任务,因为它们的持续时间超过50毫秒。下图显示了每个长任务的阻塞时间:
因此,虽然在主线程上运行任务花费的总时间为560毫秒,但只有345毫秒的时间被视为阻塞时间。
TBT时间(秒) | 速度 |
---|---|
0-300 | 绿色(快速) |
300-600 | 橙色(中等) |
超过600 | 红色(慢) |
FPS 每秒绘制帧数(Frames Per Second)
帧率是视频设备产生图像(或帧)的速率,用每秒可以重新绘制的帧数(Frames Per Second,FPS)表示。
重新绘制可能需要重新计算样式、布局和绘制,如果每帧绘制到屏幕的时间在 16.7 ms 以上,每秒绘制的帧数就会小于 60 帧,人眼就能感受到页面出现卡顿,所以 FPS 是衡量应用流畅度的一个非常重要的指标,60fps 是页面流畅的目标,可以为每次绘制提供 16.7ms 的时间预算。
既然帧率与页面重新绘制有关,那我们可以思考两个问题:
FPS 在电影和游戏中最为常见,但现在被广泛用作衡量网站和网络应用程序性能的指标。
在 Web 性能中,FPS 最常用于衡量动画的性能:如果 FPS 太低,动画会卡顿。
FPS 也可以作为用户与页面交互时页面响应性的一般度量。例如,如果将鼠标移到某个页面元素上会触发执行 JavaScript 来更新页面,这可能会触发回流和重绘,这需要在帧中完成,如果浏览器处理帧的时间过长,将会出现卡顿现象。
再例如,如果在滚动页面时会触发很多复杂的页面更新,并且浏览器无法保持可接受的帧率,那么滚动页面时会显得迟缓或卡顿。
重新绘制到屏幕可能需要从构建 DOM 树开始、重新计算样式、布局、绘制等,我们需要尽可能的避免触发这些流程,例如使用 CSS 修改 opacity 属性就不会触发重新布局,可以减少绘制时间。
所以在实现动画时,建议使用性能成本低的 CSS 属性,而不要使用 JavaScript 设置元素。
浏览器从请求页面开始到接收第一字节的时间,这个时间段内包括 DNS 查找、TCP 连接和 SSL 连接。
这是一个表示页面可视区域中内容的填充速度的指标,可以通过计算页面可见区域内容显示的平均时间来衡量。
首先在浏览器中捕获页面加载的视频,然后对每 100 毫秒间隔的页面截图计算页面填充的百分比,可以得到这样一个曲线(纵轴是页面可视区域内容填充完成度,横轴是时间)。
图中的 Example 1 和 Example 2 都是在 10s 时页面填充完成,但 Example 1 在 2s 是就已经填充了 80% 的内容,而 Example 2 在 8s 时才填充 80%。
图中阴影部分的面积(即时间-内容填充百分比曲线以上部分)的大小即可表示可视区域内页面内容的填充速度,面积越小,填充速度越快。
如果用时间来衡量,可以这样计算,以此来表示页面可见区域内容显示的平均时间。
Plain Text
Example 1:Speed Index = (80% * 2) + (20% * 10)= 3.6
Example 2:Speed Index = (80% * 8) + (20% * 10)= 8.4
这个平均时间可以用来比较首屏内容完整呈现给用户的性能体验,但它计算的不是首屏内容完整呈现这一时刻,不能算是一个用时间来度量的指标。
Web Vitals
Google 在 2020 年 5 月 5 日提出了新的用户体验量化方式 Web Vitals 来衡量网站的用户体验,并将这些衡量结果用作其排名算法的一部分。过去要衡量一个网站的好坏,需要使用的指标太多了。在 Web Vitals 中,Google 确定了三个主要衡量指标:
这三个指标已经经过了一段时间的验证,如 LCP 在 WICG 已经孵化至少1年以上,FID 在 Google Chrome Labs 上已经实施2年以上,LCP 和 CLS (相关布局不稳定 API)已于前几年入了 W3C 草拟标准
web-vitals
库Web Vitals
其它性能指标