你不能管理你不能衡量的东西。——彼得·德鲁克

宽宏大量
引用的是彼得·德鲁克的一句话,“如果你不能衡量一件事,你就不能管理它”,绩效也是如此。没有准确的方案来衡量性能,就没有办法进行优化。那么对于我们来说,可以用什么指标来衡量页面性能和用户体验呢?我从以下几个角度给大家一一讲解:性能API页面流畅度
英国制药学会会员
英国皇家空军
第一次屏幕性能
FP、FCP、FMP
病毒
性能API
相信前端的同学应该对性能API比较熟悉。通常我们把浏览器提供的可以测量和采集的API统称为性能API。这种类型的对象可以通过调用只读属性window.performance
在日常工作中,为了计算一个任务的耗时,我们通常使用Date.now来创建任务执行前后的两个时间,最后取两者之差作为任务执行的耗时。但是Date.now有两个问题:返回的时间戳是自1970年1月1日00:00:00 UTC以来的毫秒数,具体取决于系统时间。精度只有毫秒。
为了精确计算性能,我们可以选择Performance API提供的performance.now进行高精度计算。其特点是:
基于时间戳的页面打开时间计算
精确到微秒
在下图中,您可以直观地看到它们之间的区别:
页面流畅度英国制药学会会员
帧率,一般来说,对于网页,最佳帧率是60 FPS。越接近这个值,页面就越平滑。如果帧率远低于这个值,用户可能会明显感觉卡顿。
60 FPS意味着页面需要每16.5ms渲染一次,否则会丢帧,浏览器中的Javascript执行和页面渲染会互相阻塞。如果代码中有非常复杂的逻辑占用了大量的执行时间,页面就会卡住。
在Chrome的devtools中,我们可以执行Cmd+Shift+P进入show fps快速打开fps面板,如下图所示:
通过观察FPS面板,我们可以方便地监控当前页面的流畅度。如果我们想在代码中监控当前页面的FPS帧率,我们可以参考下面的示例代码:var lastTime = performance.nowvar frame = 0;var lastFameTime = performance . now;var loop = function { var now = performance . now;var fs =;lastFameTime = nowvar fps = Math.roundframe++;if { var fps = math . round/);帧= 0;lastTime =现在;};window.requestAnimationframe}
requestAnimationframeWindow.requestAnimationframe告诉浏览器你要执行一个动画,并要求浏览器在下次重绘前调用指定的回调函数更新动画。
这里借用MDN的描述,顾名思义就是传入一个函数,让浏览器在下一次渲染之前调用。那么基于这个特性,结合上面提供的FPS计算示例代码,我们可以发现,如果连续调用requestAnimationframe,那么每次调用的间隔应该在16.7ms左右,也就是可以满足我们对页面流畅度60 FPS的要求。您可以使用下面的代码在控制台上执行它并进行试验:
设last time = 0;const measure = = > { console . log-last time } ms `);lastTime = Date.nowrequestAnimationframe};衡量;
|第一次屏幕性能作为我们最为关注的核心指标之一,首屏的性能在性能优化场景中占据了相当大的比重。那么,我们对第一屏的性能有什么衡量标准呢?
为了解决这个问题,谷歌提出了一系列以用户体验为中心的性能指标。
FP、FCP、FMPFP代表浏览器第一次向屏幕传输像素的时间。只能说明目前已经开始绘图,实际意义不大。
FCP第一次代表浏览器将“内容”绘制到屏幕上,而不是白色)。
相比之下,FCP指的是浏览器第一次从DOM中提取内容。例如:文本、图片、SVG、画布元素等。这个时间点被称为FCP。
FMP表示页面中有意义的内容开始出现在屏幕上的时间点。也是我们衡量用户加载体验的主要指标。
本质上,FMP是一个主观认知指数,就是通过一个算法来猜测某个时间点可能是FMP,但是计算方法过于复杂,不准确。后来Google抛弃了FMP的检测算法,采用了更明确的客观指标——LCP。
病毒
核心Web指标是适用于所有网页的Web指标的子集。每个网站所有者都应该衡量这些指标,这些指标也会显示在所有的谷歌工具中。每个核心Web指标代表用户体验的一个不同方面,可以实际测量并反映以用户为中心的关键结果的真实体验。
目前,Web的核心指标由三个方面组成——页面加载性能、交互性和视觉稳定性,包括以下三个指标和阈值:
最大含量涂料:最大含量涂料,测量负载性能。为了提供良好的用户体验,LCP应该在页面首次开始加载后的2.5秒内发生。首次输入延迟:首次输入延迟,测量交互性。为了提供良好的用户体验,页面的FID应该小于或等于100ms。
累积布局偏移:累积布局偏移并测量视觉稳定性。为了提供良好的用户体验,页面的CLS应该保持在0.1。或者更少。
1)LCP
LCP关注第一个屏幕中最大元素的渲染时间。与FCP不同,FCP更注重浏览器何时开始绘制内容,比如加载页面或骨架屏幕,这些都没有实用价值,所以LCP比FCP更适合作为首屏指标。
以详情页为例。在FCP,产品图片不加载。这时候对于用户来说,一个近乎白屏的页面是没有交互价值的。在LCP中,图片已经加载完毕,首屏主要元素也差不多加载完毕。作为首屏时间,此时的时间更接近用户的体感。既然LCP是根据页面上面积最大的元素的渲染时间来决定的,那么包括哪些元素呢?画
嵌入svg的图像元素
视频的封面
url加载的背景图像
特性
在webpagetest上可以直观的看到当前LCP元素的细节。
元素面积的计算规则如下:视口中可见元素的大小,如果它超出可见区域或被剪切、阻挡等。,将不计入元素的大小。
对于图片元素,大小是图片的实际大小和原始大小的较小值,即Min。
对于文本元素,只取能覆盖文本的最小矩形区域。
对于所有元素,边距、填充、边框等。不算在内。
2)FID
FID指标是指用户第一次与网站交互到浏览器响应事件之间的实际延迟时间。想象一下,如果你点击一个按钮后页面没有变化,需要2-3秒才能开始响应。可想而知,体验非常糟糕。
FID判断的交互行为有:
点击、触摸、按键等。
事件绑定的行为,例如在dom上注册的click事件。
那么为什么会有交互延迟呢?例如,我在按钮上注册了一个单击事件,例如:
btn.addEventListener => { //做点什么})
不出所料,当用户点击按钮时,回调函数会被直接触发,但如果当前主线程被渲染和长任务占用,这个回调的执行会被延迟,导致FID时长增加。而FID作为一种“非客观值”,需要用户交互来采集,用户交互的时机也会影响指标的采集和统计。

3)CLS
CLS是一个用来衡量视觉界面稳定性的指标,指页面产生的连续累积布局偏差分数。在我们的日常业务中,经常会用到懒加载、骨架屏等。以较低的成本显示页面框架,然后使用动态呈现来填充页面内容。如果此时布局发生变化,比如动态加载的元素大小与原来占用的元素大小不同,就可能导致用户误操作,影响用户体验。CLS的存在就是为了衡量这样的问题。
当我们谈到布局偏差时,我们的意思是页面中一个可见元素的起始位置发生了变化,但元素的添加或删除不会触发布局偏差。那么如何定义偏移量的连续累加呢?有以下几个要素:CLS不计算整个页面周期的偏移量得分之和,而是计算累计值最高的连续布局偏移量。
如果偏移间隔小于1s,且整个窗口的最大持续时间为5s,则计为连续偏移。
诊断工具
|开发工具工具是和前端同学打交道最多的工具之一,主要用来查看日志、网络请求、调试页面等。我们也可以用它来分析页面性能。
网络
如上图所示,这是我们熟悉的网络接口,我用红框大致划分了功能:
选项:Preverse Log可以在面板中保留网络请求,在页面重定向或者页面跳转时可以保留上一页的日志;禁用缓存可以屏蔽浏览器的http缓存机制;右边的No throtting选择器可以模拟当前的网络状态。
请求列表,请求状态
传输音量:默认显示gzip/br的压缩大小。
瀑布:资源加载的时间顺序和每一步的时间消耗
表演
性能面板可以提供更专业的性能信息。
网页测试WebPageTest是一个在线性能分析平台。除了常用的cwv性能数据,还有性能、灯塔报告、页面对比等功能。
输入URL后,我们可以简单地选择一个简单的配置进行测试。默认情况下,它将被测试三次。在这里,我们可以看到页面的一些核心指标,点击相应的指标进行更详细的分析。在瀑布页面上,我们还可以直观的看到当前页面的请求顺序、请求时间和关键节点。优化手段
网络传输优化这里我们关注三个时间指示器:
总连接时间:总连接时间。
TTFB:第一个字节的耗时传输
内容下载:内容传输需要时间。
总连接时间导致连接时间过长的因素可能有很多:
与机器客户端的物理距离太长。
重复连接,页面中使用多个不同的域名,每次都需要重新建立连接。
客户端网络环境问题
那么我们可以采取什么措施来解决这些问题:CDN用于动态加速主域名,缓存资源域名,利用边缘节点的特性缩短用户请求距离。
预连接用于预构建域名,同时对域名进行折叠,可以减少http2情况下构建域名的耗时。
充分利用http缓存和servicesworker请求拦截的特点,将可缓存的资源缓存在本地,减少网络请求的数量。
TTFB +内容下载
TTFB是从发起请求到收到服务器请求的第一个字节的时间。一般来说,如果首屏html请求的TTFB能达到100ms以内,用户就已经有很好的体验了。如果超过500ms,用户会明显感觉到白屏。准确的说,TTFB是完成DNS查询、TCP握手、SSL握手后,从发起HTTP请求消息到收到服务器第一条响应消息的时间差,大约等于一个RTT+。
那么在耗时较长的情况下如何优化TTFB呢?可以参考以下方式:减少请求传输,避免无用信息。
减少服务器处理时间。
对于第一屏的HTML内容的流式渲染,由于浏览器并不依赖于下载完整的HTML来解析HTML,而是渲染其中的一部分,所以服务器可以先通过流式渲染返回一些准备好的内容,而不是等所有内容都准备好了再返回。
懒加载:优先返回必要的内容,比如超长页面。可以先返回第一屏看到的内容,然后通过异步加载渲染剩下的,通过多个接口进行请求。
那么,TTFB是不是越短越好?其实也不尽然。我们需要在TTFB和内容下载之间取得良好的平衡。比如当我们开启gzip/br压缩时,TTFB必然呈现上升趋势,但当相应的资源量变小时,就会加快传输时间,减少内容下载的时间。所以要注重用户的真实体验,而不是一味的盯着时间进行优化。
预载
预载是指预加载。预加载的方式有很多种,终端内外也有不同的方案。比较常见的有:
预加载标签:
工人预载:闪光器、工作箱预载等。
Zcache:通过资源离线打包的方式在客户端预加载。
相关链接
灯塔得分计算器:https://googlechrome.github.io/lighthouse/scorecalc/
网页测试:

https://www.webpagetest.org/
网络重要信息:
https://web.dev/vitals/
web-vitals - Github:
https://github.com/GoogleChrome/web-vitals


