前端性能优化 - 性能指标
什么是 Web 性能
简单来说就是网站够不够快。
- 打开速度
- 动画效果
- 表单提交
- 列表滚动
- 页面切换斜体
- …
MDN 上的 Web 性能定义:Web 性能是网站或应用程序的客观度量和可感知的用户体验。
- 减少整体加载时间:减小文件体积、减少 HTTP 请求、使用预加载
- 网站尽快可用:仅加载首屏内容,其他内容根据需要进行懒加载
- 平滑和可交互性:使用 CSS 替代 JS 动画、减少 UI 重绘
- 感知表现:页面可能不能做的更快,但是可以让用户感觉更快。耗时操作要给用户反馈,比如加载动画、进度条、骨架屏等提示信息
- 性能测定:性能指标、性能测试、性能监控持续优化
为什么关注 Web 性能
- 用户留存
- 网站的转化率
- 体验与传播
- 搜索排名
- 客户投诉
- 提升工作绩效
- …
如何进行 Web 性能优化
首先需要了解性能指标,多块才算快?
使用专业的工具可量化地评估网站或应用的性能表现;
立足于网站页面响应的生命周期,分析出造成较差性能表现的原因;
技术改造、可行性分析等具体的优化实施,迭代优化;
性能指标
- RAIL 性能模型
- 基于用户体验的核心指标
- 新一代性能指标:Web Vitals
性能测量
- 浏览器 DevTools 调试工具
- 网站监控分析
- 性能监控分析
- …
- 灯塔(Lighthouse)
- 网站整体质量评估,并给出优化建议
- WebPageTest
- 多测试地点
- 全面的优化报告
- …
生命周期
网站页面的生命周期,通俗地讲就是从我们在浏览器的地址栏中输入一个 URL 后,到整个页面渲染出来的过程。整个过程包括域名解析,建立 TCP 连接,前后端通过 HTTP 进行会话,压缩与解压缩,以及前端的关键渲染路径,把这些阶段拆解开来看,不仅能容易地获得优化性能的启发,而且也能为今后的前端工程师之路构建出完整的知识框架。
优化方案
- 发出请求到收到响应的优化,比如 DNS 查询、HTTP 长连接、HTTP 2、HTTP 压缩、HTTP 缓存等。
- 关键渲染路径优化,比如是否存在必要的重绘和回流。
- 加载过程的优化,比如延迟加载,是否有不需要再首屏展示的非关键信息,占用页面加载时间。
- 资源优化,比如图片、视频等不同的格式类型会有不同的使用场景,在使用的过程中是否恰当。
- 构建优化,比如压缩合并、基于 webpack 构建优化方案等.
- …
Web 性能指标
我们已经知道性能的重要性,但当我们讨论性能的时候,让一个网页变得很快,具体是指哪些?
实际上性能是相对的:
- 对于一个用户来说而言,一个站点可能速度很快(在具有功能强大的设备的快速网络上),而对于另一用户而言,一个站点可能会较慢(在具有低端设备的慢速网络上)。
- 两个站点可能会在完全相同的时间内完成加载,但一个站点似乎加载速度更快(如果它逐步加载内容,而不是等到最后显示任何内容)。
- 一个网站可能会出现快速加载但后来(在全部或没有)慢慢地响应用户的交互。
所以在讨论性能的时候,精确的、可量化的指标很重要。
但是,仅仅因为一个度量标准是基于客观标准并且可以定量地度量的,并不意味着这些度量是有用的。对于 Web 开发人员来说,如何衡量一个 Web 页面的性能一直是一个难题。
最初我们可以使用 Time To First Byte、DOMContentLoaded 和 Load 这些衡量文档加载速度的指标,但它们不能直接反应用户视觉体验。
为了能衡量用户视觉体验,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 进行渲染,这样可以保持动画效果的一致性,并且避免卡顿;
- 空闲(Idle):当使用 JavaScript 主线程的时候,应该把任务划分到执行时间小于 50ms 的片段中去,这样可以释放线程以进行用户交互;
- 加载(Load):应该在小于 1s 的时间内加载完成你的网站,并可以进行用户交互。
根据网络条件和硬件的不同,用户对性能的理解也有所不同。例如,通过快速地 Wi-Fi 连接在功能强大的台式机上加载站点通常在 1 秒内完成,用户对此已经习以为常。在 3G 连接速度较慢的移动设备上加载网站需要花费更多的时间,因此移动用户通常更有耐心,在移动设备上加载 5S 是一个更现实的目标。
响应
指标:应该尽可能快速的响应用户,应该在 100ms 以内响应用户输入。
网站性能对于响应的方面的要求是,在用户感知延迟之前接收操作的反馈。比如用户进行文本输入、按钮单击、表单切换及启动动画等操作后,必须在 100ms 内收到反馈,如果超过 100ms 的时间窗口,用户就会感知延迟。
看似很基本的用户操作背后,可能会隐藏着复杂的业务逻辑处理及网络请求与数据计算。对此我们应当谨慎,将较大开销的工作放在后台异步执行,而即便后台处理要数百毫秒才能完成的操作,也应当给用户提供及时的阶段性反馈。
比如在单击按钮向后台发起某项业务处理请求时,首先反馈给用户开始处理的提示,然后在处理完成的回调后给予反馈提示。
动画
指标:展示动画的时候,每一帧应该以 10 ms 进行渲染,这样可以保证动画效果的一致性,避免卡顿。
前端所涉及的动画不仅需要酷炫的 UI 动效,还包括滚动和触摸拖动等交互效果,而这一方面的性能要求就是流畅。人眼具有视觉暂留特性,就是当光对视网膜所产生的视觉在光停止作用后,仍能保留一段时间。
研究表明这是由于视神经存在反应速度造成的,其值是 1/24 s,即当我们所见的物体移除后,该物体在我们眼中并不会立即消失,而会延续 1/24 s 的时间。对动画来说,无论动画帧率有多高,最后我们仅能分辨其中的 30 帧,但越高的帧率会带来更好的流畅体验,因此动画要尽力达到 60fps 的帧率。
目前大多数设备的屏幕刷新率为 60 次/秒,那么浏览器渲染动画或页面的每一帧的速率也需要跟设备屏幕的刷新率保持一致。所以根据 60 fps 帧率的计算,每一帧画面的生成都需要经过若干步骤,一帧图像的生成预算为 10ms (100ms / 60 ≈ 16.66ms),除去浏览器绘制新帧的时间,留给执行代码的时间仅为 10ms 左右。如果无法符合此预算,帧率会下降,并且内容会在屏幕上抖动。这个现象通常称为卡顿,会对用户体验产生负面影响。具体的优化策略,后面再详细介绍。
https://googlechrome.github.io/devtools-samples/jank/。
空闲
指标:当使用 JavaScript 主线程的时候,应该把任务划分到执行时间小于 50 ms 的片段中去,这样可以释放线程以进行用户交互。
要使网站响应迅速、动画流畅,通常都需要较长的处理时间,但以用户为中心来看待性能问题,就会发现并非所有的工作都需要在响应和加载阶段完成,我们完全可以利用浏览器的空闲时间处理可延迟的任务,只要让用户感觉不到延迟即可。利用空闲时间处理延迟,可减少预加载的数据大小,以保证网站或应用快速完成加载。
为了更加合理地利用浏览器的空闲时间,最好将处理任务按 50 ms 为单位分组。
这么做就是保证用户在发生操作后的 100ms 内给出响应。
加载
指标:首次加载应该在小于 5s 的时间内加载完成,并可以进行用户交互。对于后续加载,则是建议在 2 秒内完成。
用户感知要求我们尽量在 5s 内完成页面加载,如果没有完成,用户的注意力就会分散到其他事情上,并对当前处理的任务产生中断感。需要注意的是,这里的 5s 内完成加载并渲染出页面的要求,并非要完成所有页面资源的加载,从用户感知体验的角度来说,只要关键渲染路径完成,用户就会认为全部加载已完成。
对于其他非关键资源的加载,延迟到浏览器空闲时段在进行,是比较常见的渐进式优化策略。比如图片懒加载、代码拆分等优化手段。
基于用户体验的性能指标
基于用户体验的性能指标是 Google 在 web.dev 提出的。其中包括以下几个比较重要的性能指标:
- FCP
- LCP
- FID
- TTI
- TBT
- CLS
First Contentful Pant(FCP)
FCP(First Contentful Paint)首次内容绘制,浏览器首次绘制来自 DOM 的内容的时间,内容必须是文本、图片(包括背景图)、非白色的 canvas 和 SVG,也包括带有正在加载中的 Web 字体的文本。
即首屏第一次开始看到页面内容,但仅仅有内容,并不意味着是有用的内容,也不意味着有用户要消费的内容。
速度指标
FCP 时间(以秒为单位) | 颜色编码 | FCP 分数(HTTP 存档百分位数) |
---|---|---|
0-2 | 绿色(快速) | 75-100 |
2-4 | 橙色(中等) | 50-74 |
超过4 | 红色(慢) | 0-49 |
优化方案:
https://web.dev/fcp/#how-to-improve-fcp
Largest Contentful Paint(LCP)
LCP(Largest Contentful Paint)最大内容绘制,可视区域最大的内容元素呈现在屏幕上的时间,用以估算页面的主要内容对用户可见时间。
LCP 考虑的元素:
<img>
元素<image>
元素内的<svg>
元素<video>
元素(封面图)- 通过
url()
函数加载背景图片的元素 - 包含文本节点或其他内联级文本元素子级的块级元素
为了提供良好的用户体验,网站应力争使用 2.5 秒或更短的 “最大内容绘制”。为确保您达到大多数用户的这一目标,衡量移动设备和台式机设备的页面加载量的第 75 个百分位数是一个很好的衡量标准。
速度指标
LCP 时间(以秒为单位) | 颜色编码 |
---|---|
0-2.5 | 绿色(快速) |
2.5-4 | 橙色(中等) |
超过4 | 红色(慢) |
优化方案:
https://web.dev/optimize-lcp/
First Input Delay(FID)
FID(First Input Delay)首次输入延迟,从用户第一次与页面交互(例如点击链接、点击按钮等)到浏览器实际能够响应该交互的时间。
输入延迟是因为浏览器的主线程正忙于做其他事情,所以不能响应用户。发生这种情况的一个常见原因是浏览器正忙于解析和执行应用程序加载的大量计算的 JavaScript。
第一次输入延迟通常发生在第一次内容绘制(FCP)和可持续交互时间(TTI)之间,因为页面已经呈现了一些内容,但还不能可靠地交互。
速度指标
FID 时间(以毫秒为单位) | 颜色编码 |
---|---|
0-100 | 绿色(快速) |
100-300 | 橙色(中等) |
>300 | 红色(慢) |
优化方案:
https://web.dev/fid/#how-to-improve-fid
https://web.dev/optimize-fid
Time to Interactive(TTI)
表示网页第一次 完全达到可交互状态 的时间点,浏览器已经可以持续地响应用户的输入。完全达到可交互状态的时间点是在最后一个长任务(Long Task)完成的时间,并且在随后的 5 秒内网络和主线程是空闲的。从定义上来看,也可以被叫做可持续交互时间或可流畅交互时间。
长任务指需要 50 ms 以上才能完成的任务。
速度指标
TTI 时间(以秒为单位) | 颜色编码 |
---|---|
0-3.8 | 绿色(快速) |
3.9-7.3 | 橙色(中等) |
7.3 以上 | 红色(慢) |
优化方案:
https://web.dev/tti/#how-to-improve-tti
Total Block Time(TBT)
Total Block Time(TBT)总阻塞时间,度量 FCP 和 TTI 之间的总时间,在该时间范围内,主线程被阻塞足够长的时间导致输入无响应。
只要存在长任务,该线程就会被视为 “阻塞”,该任务在主线程上运行超过 50 ms,用户很可能注意到延迟并感觉页面缓慢或超时。
速度指标
TTI 时间(以毫秒为单位) | 颜色编码 |
---|---|
0-300 | 绿色(快速) |
300-600 | 橙色(中等) |
>600 | 红色(慢) |
优化方案:
https://web.dev/tbt/#how-to-improve-tbt
Cumulative Layout Shift(CLS)
Curmulative Layout Shift(CLS)累计布局偏倚,CLS 会测量在页面整个生命周期中发生的每个意外的布局移位的所有单独布局移位分数的总和,它是一种保证页面的视觉稳定性从而提升用户体验的指标方案。
速度指标
CLS 时间(以毫秒为单位) | 颜色编码 |
---|---|
0-0.1 | 绿色(快速) |
0.1-0.25 | 橙色(中等) |
>0.25 | 红色(慢) |
优化方案:
https://web.dev/cls/#how-to-improve-cls
https://web.dev/optimize-cls
Web Vitals
Google 开发了很多实用指标和工具,帮助衡量用户体验和质量,从而发掘优化点。
Web Vitals 计划降低了学习成本,为网站体验提供了一组统一的质量衡量指标 - Core Web Vitals,其中包括加载体验、交互性和页面内容的视觉稳定性。
有很多方法可以优化网站的用户体验。如果可以预先了解最佳的优化衡量方案,可以大大节省时间和成本。
Google 在 2020 年 5 月 5 日提出新的用户体验量化方式 Web Vitals 来衡量网站的用户体验,并将这些衡量结果用作排名算法的一部分。
Core Web Vitals 与 Web Vitals
Core Web Vitals 是应用于所有 Web 页面的 Web Vitals 的子集,是其最重要的核心。
- 加载性能(LCP)- 显示最大内容元素所需时间
- 交互性(FID)- 首次输入延迟时间
- 视觉稳定性(CLS)- 累积布局配置偏移
测试 Web Vitals
性能测试工具,比如 Lighthouse
实用 web-vitals 库
实用浏览器插件 Web Vitals
参考链接
https://web.dev/vitals