探究007性能指标的实现方式
一、Performance 对象
007性能指标是利用了Performance
对象,可以通过window.performance
获取Performance
。
Performance
可以获得性能数据(timing
)、内存数据(memory
)等。这里仅介绍performance.timing
属性,其他 API 可参阅后面的链接。
下面按照触发顺序看一下各个属性的含义。
1. prompt for unload
上一个页面卸载
navigationStart
:在同一个浏览器上下文中,前一个网页(与当前页面不一定同域)unload
的时间戳,如果无前一个网页 unload ,则与fetchStart
值相等unloadEventStart
:前一个网页(与当前页面同域)unload
的时间戳,如果无前一个网页unload
或者前一个网页与当前页面不同域,则值为 0unloadEventEnd
:和unloadEventStart
相对应,返回前一个网页unload
事件绑定的回调函数执行完毕的时间戳
2. 重定向
redirectStart
:第一个 HTTP 重定向发生时的时间。有跳转且是同域名内的重定向才算,否则值为 0redirectEnd
:最后一个 HTTP 重定向完成时的时间。有跳转且是同域名内的重定向才算,否则值为 0fetchStart
:浏览器准备好使用 HTTP 请求抓取文档的时间,这发生在检查本地缓存之前
3. DNS解析
domainLookupStart
:DNS 域名查询开始的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与fetchStart
值相等domainLookupEnd
:DNS 域名查询完成的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与fetchStart
值相等
4. TCP三次握手
connectStart
:HTTP(TCP) 开始建立连接的时间,如果是持久连接,则与fetchStart
值相等,如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接开始的时间connectEnd
:HTTP(TCP) 完成建立连接的时间(完成握手),如果是持久连接,则与fetchStart
值相等,如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接完成的时间secureConnectionStart
:HTTPS 连接开始的时间,如果不是安全连接,则值为 0
5. 请求数据
requestStart
:HTTP 请求读取真实文档开始的时间(完成建立连接),包括从本地读取缓存,连接错误重连时,这里显示的也是新建立连接的时间responseStart
:HTTP 开始接收响应的时间(获取到第一个字节),包括从本地读取缓存responseEnd
:HTTP 响应全部接收完成的时间(获取到最后一个字节),包括从本地读取缓存
6. processing
,JS执行、DOM解析渲染
domLoading
:开始解析渲染 DOM 树的时间,此时Document.readyState
变为loading
,并将抛出readystatechange
相关事件domInteractive
:完成解析 DOM 树的时间,Document.readyState
变为interactive
,并将抛出readystatechange
相关事件domContentLoadedEventStart
:DOM 解析完成后,网页内资源加载开始的时间,文档发生DOMContentLoaded
事件的时间domContentLoadedEventEnd
:DOM 解析完成后,网页内资源加载完成的时间(如 JS 脚本加载执行完毕),文档的DOMContentLoaded
事件的结束时间domComplete
:DOM 树解析完成,且资源也准备就绪的时间,Document.readyState
变为complete
,并将抛出readystatechange
相关事件
7. load
事件开始
loadEventStart
:load
事件发送给文档,也即load
回调函数开始执行的时间,如果没有绑定load
事件,值为 0loadEventEnd
:load
事件的回调函数执行完毕的时间,如果没有绑定load
事件,值为 0
看完上面的属性,是不是有似曾相识的感觉,就是那个常见的问题"浏览器输入一个URL会依次发生什么",只不过performance
精确获取了这些时间。
二、007性能指标
在源码中可以看到007性能指标的计算方法。007的性能指标包括:
- DNS 连接耗时
- TCP连接耗时
- 后端响应时间
- HTML 页面下载时间
- DOM 时间
- 首次加载耗时
- 整页耗时
- 解析 DOM 树耗时
它们的计算方式如下:
performance.timing
即将被废弃,取而代之的是PerformanceNavigationTiming
,绝大部分 API 是差不多的,只是后者换成了相对时间,前者是时间戳,即绝对时间。
可以试试下面的代码:
三、相关问题
1、对于Vue这样的单页应用,路由跳转后的页面加载会另外计算吗?
不会。路由跳转不会触发unload
事件。另外,试验也发现,跳转后的页面打印的performance
的domloing
、fetchStart
的时间与上一页面相同。
所以对跳转后的页面做的优化并不会影响到首屏的时间,比如对二次页面的预加载等手段。
2、不同工具的首屏时间不一致?
这很常见。首屏时间的计算方式有多种,有的人用加载最慢的图片的时间点 - navigationStart,有的人用加载最慢的图片的时间点 - loadEventStart,还有的会区分SSR和SPA应用。
首屏时间指的是浏览器显示第一屏页面所消耗的时间,包含了DNS解析、TCP握手、资源加载、DOM解析等时间,只要能囊括这些时间的指标都可以使用,毕竟使用中更多的是横向对比和纵向对比,而不是对比指标数据本身。
3、 如何减少首屏时间?
从首屏的概念和其包含的阶段可以看出,只要能减少其中包含步骤的时间,就能降低首屏时间。
常用方法包括: - 图片和JS的懒加载、按需加载 - 使用CDN资源 - 文件压缩和合并 - 使用http2 - 使用缓存