【前端】性能指标
Dandelion 10/12/2022 performance
# 概述
# 性能优化指标
- FP:First Paint,记录首次绘制像素的时间
- 记录的那一刻,DOM 内容还没开始绘制
- FCP:First Contentful Paint,记录首次内容绘制的时间
- 只有当 DOM 内容发生变化(如渲染出一段文字),才会记录 FCP
- FP 和 FCP 是白屏相关的指标,越小越好,2 秒内属于优秀范围
- LCP:Largest Contentful Paint,用于记录视窗内最大元素的绘制时间
- 该指标不是记录某一时刻,而是随着页面渲染,实时变化。该指标会在用户首次交互后停止记录
- FP/FCP 仅记录内容开始加载的那一刻,但用户希望看到的内容并未呈现,而 LCP 会持续更新,表示页面的主要内容何时呈现
- 2.5 秒内属于优秀范围
- TTI:Time To Interactive,首次可交互时间
- 满足条件:从 FCP 指标后开始计算;持续 5 秒内无长任务(执行时间超过 50 ms)且无两个以上正在进行中的 GET 请求;往前回溯至 5 秒前的最后一个长任务结束的时间
- 很重要的用户体验指标,代表着页面何时能真正进入可用状态
- FID:First Input Delay,首次输入延迟
- 用于记录在 FCP 和 TTI 之间,用户首次与页面交互时响应的延迟
- 如果其中有长任务发生的话,那势必会造成响应时间延长。推荐响应用户交互在 100ms 以内
- TBT:Total Blocking Time,总阻塞时间
- 用于记录 FCP 到 TTI 之间所有长任务的阻塞时间总和
- 每个长任务的阻塞时间就等于它所执行的总时间减去 50ms
- 这个指标的高低也影响了 TTI 的高低,或者说和长任务相关的几个指标都有关联性
- CLS:Cumulative Layout Shift,累计位移偏移
- 用于记录页面上非预期的位移波动
- 如,在页面渲染过程中,突然插入一张巨大的图片,或点击某个按钮,突然动态插入一块内容等,非常影响用户体验
- 计算公式:位移距离 x 位移影响的面积
- CLS 推荐值小于 0.1,越低说明页面越稳定,用户体验越好
- 并不是所有布局移动都是不好的,很多 web 网站都会改变元素的开始位置,只有当布局移动是非用户预期的,才是不好的
# 三大核心指标
Google 在 2020 年 5 月提出了 Web Vitals,这是谷歌定义的衡量一个网站用户体验的基本指标。
Core Web Vitals:LCP、FID、CLS。
- LCP:最大内容绘制
- 用于记录视窗内最大元素的绘制时间,该时间会随着页面渲染变化而变化
- 页面中的最大元素在渲染过程中可能会发生改变,该指标会在用户第一次交互后停止记录
- 谷歌要求 LCP 最好在页面首次开始加载后的 2.5s 内发生
- LCP 并不会计算所有元素,仅关注下面的元素:
1. image 元素 2. image 元素内的 svg 元素 3. video 元素 4. 通过 url() 函数加载背景图片的元素 5. 包含文本节点或其他内联文本元素的块级元素
1
2
3
4
5 - LCP 优化可以考虑的因素:服务端响应时间;JS 和 CSS 引起的渲染卡顿;资源加载时间;客户端渲染
- FID:首次输入延迟
- 用于记录用户首次与页面交互时响应的延迟,即从用户首次与页面进行交互到浏览器实际上能够响应该交互之间的时间
- 用于衡量页面交互性,谷歌要求页面的 FID 最好小于 100ms
- FID 在 FCP 和 TTI 之间,这个阶段页面已经部分呈现,但还不具备完全可持续交互的状态
- 如果其中有长任务发生的话,那么势必会造成响应时间变长
- FID 优化可以考虑的因素:减少第三方代码的影响;减少 JS 的执行时间;最小化主线程工作;减小请求数量和请求文件大小
- CLS:累计布局位移
- 用于衡量视觉稳定性,有助于量化用户体验意外布局位移的频率
- 谷歌要求页面的 CLS 最好保持小于 0.1
- CLS 优化可以考虑的因素
- 图片或视频元素有大小属性,给他们保留一个空间大小,设置 width/height
- 不要在一个已存在的元素上面插入内容,除了相应用户输入
- 使用 animation 或 transition 而不是直接触发布局改变
# 性能指标监测
- npm 包
- 谷歌提供的 npm 包:
npm install web-vitals
- 使用方式:
import { getLCP, getFID, getCLS } from 'web-vitals'; getCLS(console.log); getFID(console.log); getLCP(console.log);
1
2
3
4
5
- 谷歌提供的 npm 包:
- google 插件
PageSpeed Insights
、Chrome UX Report
、Search Console
、Web Vitals Extension
、Lighthouse
- 具体步骤:
1. 首先使用 Lighthouse,在本地进行测量,根据报告给出的一些建议进行优化; 2. 发布之后,使用 PageSpeed Insights 去看下线上的性能情况; 3. 接着使用 Chrome User Experience Report API 去捞取线上过去 28 天的数据; 4. 发现数据有异常,使用 DevTools 工具进行具体代码定位分析; 5. 使用 Search Console’s Core Web Vitals report 查看网站功能整体情况; 6. 使用 Web Vitals 扩展方便的看页面核心指标情况
1
2
3
4
5
6
- 原生 API
- 主要使用
PerformanceObserver
接口 - 具体步骤:
// LCP new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { console.log('LCP candidate:', entry.startTime, entry); } }).observe({ type: 'largest-contentful-paint', buffered: true }); // FID new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { const delay = entry.processingStart - entry.startTime; console.log('FID candidate:', delay, entry); } }).observe({ type: 'first-input', buffered: true });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
- 主要使用
# 怎么查看 JS 内存使用情况
- 任务管理器
- 打开谷歌任务管理器,关注两个指标:内存占用空间;JS 使用的内存
- 内存占用空间:原生内存,Dom 节点就是存在原生内存里面
- JS 使用的内存:代表 JS 堆内存,只需要关心括号里的实时值就可以了,JS 对象就存在 JS 堆里面
- 打开谷歌任务管理器,关注两个指标:内存占用空间;JS 使用的内存
- Performance
- JS 堆占用每次下降都是 Garbage Collection(垃圾回收,GC)执行过后
- 利用 performance 来看 JS 堆的使用情况,还可以看线程在执行什么任务,占用了多久时间
- Memory 拍摄堆快照
- 通过任务管理器和 Performance 可以看到 JS 堆的大小和趋势,但没办法看到堆里面的细节
- 可以通过 Memory 模块,拍摄一个快照,借此查看细节内容,关注两列:Shallow Size 和 Retained Size
- Shallow Size:浅层大小,是对象本身的大小(不包括它内部引用的对象),这个通常不太关注
- Retained Size:保留大小,如果 GC 回收这个对象后,可以释放多少内存,这个非常关注
- Performance Monitor
- 可以理解为 Performance 的实时简化版,Performance 可以录快照,可以看到每个点比较详细的信息,但不是实时的
- Performance Monitor 是实时的,但没办法像 Performance 细节