关于前端性能指标,W3C 定义了强大的 Performance
API,其中又包括了 High Resolution Time
、 Frame Timing
、 Navigation Timing
、 Performance Timeline
、Resource Timing
、 User Timing
等诸多具体标准。
本文主要涉及 Navigation Timing
以及 Resource Timing
。截至到目前,各大主流浏览器均已完成了基础实现。
Performance
API 功能众多,其中一项,就是将页面自身以及页面中各个资源的性能表现(时间细节)记录了下来。而我们要做的就是查询和使用。
可以直接在浏览器,打开开发者模式,控制台中输入 performance ,查看相关 API。
1. 页面加载
有关页面加载的性能指标,可以在 Navigation Timing
中找到。Navigation Timing
包括了从请求页面起,到页面完成加载为止,各个环节的时间明细。
可以通过以下方式获取 Navigation Timing
的具体内容:
1
| const navTimes = performance.getEntriesByType('navigation')
|
getEntriesByType
是我们获取性能数据的一种方式。performance
还提供了 getEntries
以及 getEntriesByName
等其他方式,详细文档见:www.w3.org/TR/performa。
返回结果是一个数组,其中的元素结构如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| { activationStart: 0 connectEnd: 64.80000019073486 connectStart: 37.90000009536743 criticalCHRestart: 0 decodedBodySize: 244211 deliveryType: "" domComplete: 943.3000001907349 domContentLoadedEventEnd: 568.8000001907349 domContentLoadedEventStart: 568.5 domInteractive: 482.40000009536743 domainLookupEnd: 37.90000009536743 domainLookupStart: 37.90000009536743 duration: 943.4000000953674 encodedBodySize: 43525 entryType: "navigation" fetchStart: 5.5 firstInterimResponseStart: 0 initiatorType: "navigation" loadEventEnd: 943.4000000953674 loadEventStart: 943.4000000953674 name: "https://juejin.cn/post/6844903662020460552" nextHopProtocol: "h2" notRestoredReasons: null redirectCount: 0 redirectEnd: 0 redirectStart: 0 renderBlockingStatus: "non-blocking" requestStart: 65.09999990463257 responseEnd: 222.5 responseStart: 192.59999990463257 responseStatus: 200 secureConnectionStart: 51 startTime: 0 transferSize: 43825 type: "navigate" unloadEventEnd: 0 unloadEventStart: 0 workerStart: 0 }
|
关于各个字段的时间含义,Navigation Timing Level 2 给出了详细说明:
读取 domComplete
:
1
| const [{ domComplete }] = performance.getEntriesByType('navigation')
|
到此,我们获得了准确的页面加载时间。
2. 资源加载
资源加载对应的性能指标,可以在 Resource Timing
中找到。它包含了页面中各个资源从发送请求起,到完成加载为止,各个环节的时间细节,和 Navigation Timing
十分类似。
获取资源加载时间的关键字为 'resource'
, 具体方式如下:
1
| performance.getEntriesByType('resource')
|
返回结果通常是一个很长的数组,因为包含了页面上所有资源的加载信息。
每条信息的具体结构为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| {
connectEnd: 203.09999990463257 connectStart: 203.09999990463257 decodedBodySize: 208476 deliveryType: "cache" domainLookupEnd: 203.09999990463257 domainLookupStart: 203.09999990463257 duration: 16.800000190734863 encodedBodySize: 32054 entryType: "resource" fetchStart: 203.09999990463257 firstInterimResponseStart: 209.90000009536743 initiatorType: "link" name: "https://lf-web-assets.juejin.cn/obj/juejin-web/xitu_juejin_web/static/bytedesign.min.css" nextHopProtocol: "h2" redirectEnd: 0 redirectStart: 0 renderBlockingStatus: "blocking" requestStart: 208.80000019073486 responseEnd: 219.90000009536743 responseStart: 209.90000009536743 responseStatus: 0 secureConnectionStart: 203.09999990463257 serverTiming: [PerformanceServerTiming] startTime: 203.09999990463257 transferSize: 0 workerStart: 0 }
|
我们关注的是资源加载的耗时情况,可以通过如下形式获得:
1 2
| const [{ startTime, responseEnd }] = performance.getEntriesByType('resource') const loadTime = responseEnd - startTime
|
同 Navigation Timing
相似,关于 startTime
、 fetchStart
、connectStart
和 requestStart
的区别, Resource Timing Level 2 给出了详细说明:
实际业务中,并非所有资源加载时间都需要关注,假设只返回超过10s的资源加载情况:
1 2 3 4 5 6 7 8 9 10
| const SEC = 1000 const TIMEOUT = 10 * SEC const setTime = (limit = TIMEOUT) => time => time >= limit const isTimeout = setTime() const getLoadTime = ({ startTime, responseEnd }) => responseEnd - startTime const getName = ({ name }) => name const resourceTimes = performance.getEntriesByType('resource') const getTimeoutRes = resourceTimes .filter(item => isTimeout(getLoadTime(item))) .map(getName)
|
至此,我们介绍了两个主要的前端性能检测指标,页面加载和资源加载,分别通过Navigation Timing
和Resource Timing
来获取,通过监控这两个性能指标,就可以满足简单的前端性能检测。