前言
用户在访问 web 网页时,大部分都希望网页能够在一秒完成。事实上,加载时间每多 1 秒,就会流失 7%的用户。如果时间超过 8s 用户就会感到不耐烦、会放弃访问。这也就是著名的 “8秒原则”。
虽然当今设备及网络环境都大幅提升,但“带宽低”、“速度慢”、“内存小”的平均情况仍然是web性能瓶颈,特别是在移动端。因此多年以来,web 性能优化依旧是一个非常庞大的工程,需要制定指标、确定标准、采用优化手段、进行性能测试、确定性能指标上报、确定性能监控和预警等等。
本文将重点讲述web性能指标以及常用度量工具,希望能为你的网页性能优化提供一些参考。
一、性能度量指标
从开篇中我们知道性能很重要,但是当我们谈起 web 性能时,具体指的是什么?
首先性能的衡量是相对的,比如以下场景:
- 由于网速或设备的差异,同一个网站可能对一个用户来说访问速度很快(“性能好”),但另一个用户访问速度很慢(“性能差”)。
- 两个内容相似的网站完成加载所需的时间或许相同,但其中一个却显得加载速度更快(比如该网站逐步渐进式得加载内容,而不是等到最后才一起显示)。
- 一个网站可能看起来加载速度很快,但随后在用户操作时、用户交互的响应速度却很慢(比如操作卡顿或根本无响应)。
因此,在谈论性能时,相对重要的是做到度量精确,并且根据能够进行定量测量的客观标准来论及性能。这些标准就是指标,常用的性能指标如下:
- FCP:First Contentful Paint,首次内容绘制,测量页面从开始加载到页面内容的任何部分在屏幕上完成渲染的时间。
- FMP:First Meaningful Paint,首次有效绘制,当主要内容呈现在页面上;
- HRT:Hero Rendering Times,英雄渲染时间,度量用户体验的新指标,当用户最关心的内容渲染完成;
- TTI:Time to Interactive,可交互时间,指页面布局已经稳定,关键的页面内容是可见的,并且主进程可用于处理用户输入,基本上用户可以点击 UI 并与其交互;
输入响应(Input responsiveness,界面响应用户输入所需的时间) - PSI:Perceptual Speed Index,感知速度指数,测量页面在加载过程中视觉上的变化速度(分数越低越好);
- LCP:Largest Contentful Paint 最大内容绘制,测量页面从开始加载到最大文本块或图像元素在屏幕上完成渲染的时间。
- FID:First Input Delay,首次输入延迟,测量从用户第一次与您的网站交互(例如当他们单击链接、点按按钮或使用由 JavaScript 驱动的自定义控件)直到浏览器实际能够对交互做出响应所经过的时间。
- TBT:Total blocking time 总阻塞时间,测量 FCP 与 TTI 之间的总时间,这期间,主线程被阻塞的时间过长,无法作出输入响应。
- CLS:Cumulative Layout Shift,累积布局偏移,测量页面在开始加载和其生命周期状态变为隐藏期间发生的所有意外布局偏移的累积分数。
注:FMP 与 HRT 非常相似,但它们不一样的地方在于 FMP 不区分内容是否有用,不区分渲染出的内容是否是用户关心的。
*Core Web Vitals核心网页指标
“Web Vitals”是 Google 推出的一项计划,旨在针对在提供出色的 Web 体验方面至关重要的质量信号提供统一指南。核心网页指标是适用于所有网页的部分网页指标,应由所有网站所有者进行衡量,并且会显示在所有 Google 工具中。每个核心网页指标都代表用户体验的一个不同方面,在实际应用中是可衡量的,并且反映了以用户为中心的关键结果的真实体验。
构成 Core Web Vitals 的指标会随着时间的推移而演变。目前设定的 2020 年目标侧重于用户体验的三个方面(加载、互动和视觉稳定性),并包含以下指标阈值:
对于上述每个指标,为了确保您达到大多数用户的推荐目标,最好衡量一下网页加载的第 75 个百分位(按移动设备和桌面设备细分)。
Performance API
浏览器提供的 Performance API 是一组用于衡量 web 应用性能的标准,是上述性能指标监控数据的关键来源。
Performance 提供高精度的时间戳,精度可达纳秒级别,且不会随操作系统时间设置的影响。
当我们访问 window.performance
时可以看到它返回一个 Performance
类型的对象,以及该对象中暴露出来的几个对象和方法:
这些字段在下图中得以有效体现:
但仅仅因为某个指标基于客观标准并且能够进行定量测量,也并不一定意味着那些测量值就是有用的。我们需要自定义指标,由业务需求和用户体验来决定。
自定义指标
有时候,可能会有某个特定网站比较独树一帜,需要额外的指标来捕获完整的性能全貌。例如,LCP 指标用于测量页面的主要内容何时完成加载,但在某些情况下,最大元素并不是页面主要内容的一部分,因此 LCP 就不再适用。
为了解决这种情况,Web 性能工作组还推出了一系列较低级别的标准化 API,通过这些API我们可以实现各种自定义指标。API如下、具体使用本文不做展开:
- 用户计时 API https://w3c.github.io/user-timing/
- 长任务 API https://w3c.github.io/longtasks/
- 元素计时 API https://wicg.github.io/element-timing/
- 导航计时 API https://w3c.github.io/navigation-timing/
- 资源计时 API https://w3c.github.io/resource-timing/
- 服务器计时 https://w3c.github.io/server-timing/
比较常见的自定义指标方式是结合Performance时间 + 交互API统计时间 + js dom展示事件打点
二、RAIL 体验模型
RAIL 模型是 Chrome 团队于 2020年 发布的一种以用户为中心的性能模型,它将用户体验分解为关键操作并提供了一种考虑性能的结构。RAIL 是 response (响应)、 animation(动画)、idle(浏览器空置时间)和 load(加载)。
从这四个模块角度来思考你的产品。如果在每个模块上,你都可以达到性能优化的目标值,那么最终用户感受到的将会是极致的体验。
在 RAIL 模型中,通常建议性能阈值:
Response
:点击/轻触后100 ms
内得到响应;Animation
:每一帧的渲染在16 ms
内完成;拖拽后的页面渲染也要在16 ms
内完成;Idle
:合理地使用浏览器空闲时间;任务要在50 ms
内完成;Page Load
:加载的过程要满足“响应”目标;最重要的内容要在1000 ms
内完成加载。
在此性能目标的基础上,结合度量工具进行统计,便能对线上用户的 RAIL 性能情况得到统计和分析评估。
三、性能度量工具
很多工具能够帮助我们获取或度量分析上文中的一些通用性指标数据。
一类工具就是基于模拟器或者仿真环境机制的合成监控(Synthetic Monitoring,SYN),最典型的就是Chrome DevTools:
Chrome DevTools
Chrome 浏览器开发者工具中的 Lighthouse
和 Performance
能有效帮助我们进行性能分析:
Lighthouse
:生成性能分析报告。并且给予相关优化建议;Performace
:分析运行时数据报告,包含阻塞、重排等细节信息;
根据这两个有效工具能够帮我们分析当前页面/运行的性能情况,以便有效做出优化。具体工具使用可以看对应官网文档《Chrome-Analyze runtime performance》、《Using Lighthouse To Improve Page Load Performance》
lighthouse 的本地使用/脚本化
Nodejs 12.x
版本起支持,可以直接安装 lighthouse
在本地:
npm i -g lighthouse
简单分析,比如:
# lighthouse URL地址 参数
lighthouse https://blog.michealwayne.cn
以此为基础,我们可以用 Nodejs 写脚本,并尝试将分析工作自动化及平台化。比如 https://web.dev/measure/ 中的 PageSpeed测试。
*React Profiler 分析 React 性能
React Profiler 是 React 官方提供的性能审查工具。React 16.5
添加了对新 DevTools 分析器插件的支持。该插件使用 React 的实验性 Profiler API 来收集有关渲染的每个组件的时间信息,以便识别 React 应用程序中的性能瓶颈。使用官网说明https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html
*通过 Web Vitals库测量“Core Web Vitals”
若要衡量所有核心网页指标,最简单的方法是使用 web-vitals JavaScript 库,这是一个可用于生产环境的小型底层 Web API 封装容器,用于衡量每个指标,并且衡量方式与上述所有 Google 工具报告这些指标的方式完全一致。
借助 web-vitals 库,您可以像调用一个函数一样轻松衡量每个指标(如需查看完整的用法和 API 详情,请参阅相关文档):
import {onCLS, onFID, onLCP} from 'web-vitals';
function sendToAnalytics(metric) {
const body = JSON.stringify(metric);
// Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
(navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
fetch('/analytics', {body, method: 'POST', keepalive: true});
}
onCLS(sendToAnalytics);
onFID(sendToAnalytics);
onLCP(sendToAnalytics);
将网站配置为使用 web-vitals 库衡量核心网页指标数据并将其发送到分析端点后,下一步是汇总并报告这些数据,看您的网页是否至少有 75% 的网页访问达到建议的阈值。
*通过 webpack-bundle-analyzer 和 vue-cli report 分析模块资源大小
这两个插件不是典型的性能度量工具,但我们知道影响前端加载和执行时间的一大重要因素就是资源大小,这两个工具就是便于分析产物及依赖资源大小的典型插件。
通过webpack-bundle-analyzer,我们可以分析各个模块的大小,进行对性能影响最大的模块进行优化。vue-cli report 也集成了这功能。
真实场景的性能分析工具:WebPageTest
WebPageTest(地址https://www.webpagetest.org/),如下图所示、通过浏览器访问并
基于输入的 WebSite URL,以及选择的国家城市、浏览器类型、网络带宽等信息,启动对应的远程服务器上的浏览器进行性能分析测试。相似的还有 YSlow、PageSpeed。
其他性能测试方案
另外一些工具基于真实环境场景,这类就是真实用户监控(Real User Monitoring,RUM):
使用性能 SDK
如 APM-SkyWalking client。优点是方案与到时候线上用户一致,缺点是在测试环节样本少,需要暴露到线上。
类似的还有非常著名的 Sentry,它们都是RUM。
借助工具录视频
通过真机自动化工具直接进行页面访问时的视频录制,优点是可以和 QA 设施相结合,还能同时测试内存和 CPU 等信息。缺点是对于真实用户的监控力度不足、难以模拟各种场景。
借助端侧打点
与端侧能力相结合,通过像素检测等手段进行打点上报。优点是能兼顾线上用户及 QA 设施结合。缺点是只能作用在端内业务,无法检测端外业务。
总结
本文以web性能优化为背景,介绍前期最应该关注的内容:性能指标。
- 基础指标:FCP、FMP、LCP等
- 交互指标:TTI、FID等
- 用户感知:PSI、TBT、CLS等
另外简单介绍了RAIL性能模型以及典型的检测工具:Chrome DevTools、Lighthouse、React Profiler、Webpack Bundle Analyzer、WebPageTest。
性能指标以及度量工具是定位性能问题、制定性能优化方案的基石,下一篇将开始介绍常见性能优化手段。
作者联系方式
- michealwayne@163.com
- GitHub:http://github.com/MichealWayne
参考链接
- 《Google-Developer Loading Performace》https://developers.google.com/web/fundamentals/performance/get-started?hl=zh-cn
- 《Google-Developer Rendering Performace》https://developers.google.com/web/fundamentals/performance/rendering?hl=zh-cn
- 《Becoming Wyzerr: The 8-Second Rule》(https://medium.com/wisdom-blog/becoming-wyzerr-the-8-second-rule-84a814fa2a02)(https://medium.com/wisdom-blog/becoming-wyzerr-the-8-second-rule-84a814fa2a02)
- 《以用户为中心的性能指标》https://web.dev/user-centric-performance-metrics/
- 《WebDev RAIL 模型》https://web.dev/rail/
- 《MDN-Web 性能》https://developer.mozilla.org/zh-CN/docs/Web/Performance
- 《MDN-Performance》https://developer.mozilla.org/zh-CN/docs/Web/API/Performance
- 《嗨,送你一张 Web 性能优化地图》https://github.com/berwin/Blog/issues/23
- 《Web Vitals》https://web.dev/learn-web-vitals/
- Web vitals库 https://github.com/GoogleChrome/web-vitals