性能指标
浅谈前端性能指标
在 浏览器导航 中介绍过,通过 performance.timing
我们可以访问到一些列性能指标,且这些指标精确到纳秒级别,对我们进行性能优化是很有参考意义的。显然,这些指标中绝大多数都属于非视觉指标(Non-Visual Metrics),相反与用户体验密切度更高、更视觉化的一些「时机」是视觉指标。
# 非视觉指标
非视觉指标的计算依赖于 performance.timing
API:
const {
navigationStart,
redirectStart,
redirectEnd,
fetchStart,
// ...此处省略
} = performance.timing
下面说明根据这些属性可以直接计算出什么指标。
2
3
4
5
6
7
8
9
各值的含义见 浏览器导航,你可以选择直接阅读 W3C (opens new window)
# 重定向时间
const redirectTime = redirectEnd - redirectStart
# DNS 解析时间
const dnsTime = domainLookupEnd - domainLookupStart
# 首字节时间
const ttfbTime = responseStart - navigationStart
# TCP 连接时间
const tcpTime = connectEnd - connectStart
# 请求时间
const requestTime = responseEnd - responseStart
# DOM 树解析时间
const domParseTime = domComplete - domLoading
# DOM ready 时间
const domReadyTime = domContentLoadedEventEnd - fetchStart
2
# 页面卸载时间
const unloadTime = unloadEventEnd - unloadEventStart
# 非视觉指标的局限性
当前 SPA 盛行,基于 Vue、 React 的 Web App 层出不穷,但因为这些框架对页面内容渲染时机的改变,上述公式计算出的性能指标并不能正确反应真实的页面渲染性能了。并且,SPA 应用的假路由实现页面切换时,performance.timing
API 是不会更新的,这种情况下要实现性能监控,只能够自定义上报。
# 视觉指标
以下指标与用户视觉体验上的感知密切度更高,因而归类为视觉指标。最后说说部分指标如何计算。
# 首次绘制时间
首次渲染(First Paint,又成为 First Non-Blank Paint),表示文档中任意元素首次渲染的时间。
# 首次内容绘制时间
First Contentful Paint 代表文档中内容元素(文本、图像、Canvas,或者 SVG)首次渲染的时间。它通常情况下是无意义的渲染,比如头部和导航条。
# 首次有意义绘制时间
首次有意义渲染(First Meaningful Paint),代表首次有意义的渲染时间,它的统计在重大的布局变化之后,往往代表了用户所关心的首次渲染时间)。
# 首次可交互时间
首次可交互(First Interactive)
# 持续可交互时间
持续可交互(Consistently Interactive)。
# 指标计算
# 计算 FP、FCP
可以参考 codepen (opens new window) 这个例子,并尝试为 body 增加一个背景色或为 body
中的 div
增加内容。你可以发现:
- 当 body 没有背景色,div 中也没有内容时,不会触发任何绘制
- 当 body 有背景色,div 没有内容时,只会触发 FP
- 当 div 有内容时,不管 body 是否有颜色,都会触发 FP、FCP
核心的 JS 代码如下:
const observer = new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
const { entryType, name, startTime, duration } = entry
console.log('类型', entryType)
console.log('具体指标', name)
console.log('开始时间', startTime)
console.log('duration', duration)
}
})
observer.observe({ entryTypes: ['paint']})
2
3
4
5
6
7
8
9
10
11
# 计算 FMP
下面这个例子(见 codepen (opens new window))计算的是文字渲染出的时间,但由于 FMP 字面意思中各人对「有意义」的定义并不一致,因此实际统计 FMP,需要手动对某个认为有意义的元素进行标记,才能统计出对应元素的绘制时间。
performance.mark('text')
const performanceEntries = performance.getEntriesByType('mark')
for (const entry of performanceEntries) {
const { entryType, name, startTime, duration } = entry
console.log('entry', entry)
console.log('类型', entryType)
console.log('具体指标', name)
console.log('开始时间', startTime)
console.log('duration', duration);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
推荐阅读:网站性能指标 - FMP (opens new window) 及 前端性能监控(一)指标收集 (opens new window) 的 FMP 部分