从历史上看,咱们对客户端性能监控形式十分无限,而且还遇到了API浏览器的限度,妨碍了咱们精确地掂量客户端性能。
侥幸的是,因为有了新的面向性能的api,这种状况正在开始扭转。当初,浏览器的Performance API给咱们提供了精确度量Web页面性能的工具。
不耐烦看的同学能够间接调到开端应用办法一览
应用 Performance API 的益处
- 这些api减少了在开发工具中使用性能剖析时的教训;
- Chrome开发工具和其余工具,如Lighthouse只在开发阶段有帮忙。然而应用Performance API,咱们能够在生产中取得实在的用户度量数据(RUM - real user measurement);
- 咱们能够失去十分准确的工夫戳数据,这使得这些性能指标的剖析十分精确。
Performance 接口能够获取到以后页面中与性能相干的信息。它是 High Resolution Time API 的一部分,同时也交融了 Performance Timeline API、Navigation Timing API、 User Timing API 和 Resource Timing API。
—— MDN
High resolution time
高分辨率工夫的准确水平可达几分之一毫秒。相比之下,基于Date的工夫只能准确到毫秒。这种精确度使它成为精确测量工夫的现实工具。
由User-Agent (UA)测量的高分辨率工夫不会随着零碎工夫的任何更改而更改,因为它是从UA创立的全局时钟中获取的。
在Performance API中测量的每个测量值都是高分辨率工夫。这就是为什么你总是听到性能API是高分辨率工夫API的一部分。
Performance timeline API
Performance timeline API 是Performance API的扩大。该扩大提供了基于特定筛选条件检索性能指标的接口。
Performance Timeline API提供了以下三个办法,蕴含在性能接口中:
getEntries()
getEntriesByName()
getEntriesByType()
每个办法返回从Performance API的所有其余扩大收集的entries
列表。
PerformanceObserver
是API中蕴含的另一个接口。它次要用于察看性能时间轴(Performance Timeline),并在浏览器记录时告诉新的性能条目。它能够用来度量浏览器和 Node.js 应用程序中某些性能指标。
Performance entries
咱们用Performance API度量的货色称为entries
。以下是可供咱们应用的性能项:
mark
measure
navigation
resource
paint
frame
应用这些条目和各自的API来度量性能。
应用 Navigation timing API 和 Resource timing API测量
navigation timing API 和 resource timing API 有许多内容重叠,你能够浏览此文章具体理解他们之间的差别。
获取办法:
// Navigation Timing entries:const navigationEntries = performance.getEntriesByType("navigation")[0];// 内容{ "name": "https://awebsite.com", "entryType": "navigation", "startTime": 0, "duration": 7816.495000151917, "initiatorType": "navigation", "nextHopProtocol": "", "workerStart": 9.504999965429306, "redirectStart": 0, "redirectEnd": 0, "fetchStart": 39.72000000067055, "domainLookupStart": 39.72000000067055, "domainLookupEnd": 39.72000000067055, "connectStart": 39.72000000067055, "connectEnd": 39.72000000067055, "secureConnectionStart": 0, "requestStart": 39.72000000067055, "responseStart": 6608.200000133365, "responseEnd": 6640.834999969229, "transferSize": 0, "encodedBodySize": 0, "decodedBodySize": 0, "serverTiming": [], "unloadEventStart": 0, "unloadEventEnd": 0, "domInteractive": 6812.060000142083, "domContentLoadedEventStart": 6812.115000095218, "domContentLoadedEventEnd": 6813.680000137538, "domComplete": 7727.995000081137, "loadEventStart": 7760.385000146925, "loadEventEnd": 7816.495000151917, "type": "navigate", "redirectCount": 0}
// Resource Timing entriesconst resourceListEntries = performance.getEntriesByType("resource");
这将返回一个资源计时对象数组。单个对象看起来是这样的,可用于获取某一Web资源的前后体现信息:
{ "name": "https://awebsite.com/images/image.png", "entryType": "resource", "startTime": 237.85999999381602, "duration": 11.274999938905239, "initiatorType": "img", "nextHopProtocol": "h2", "workerStart": 0, "redirectStart": 0, "redirectEnd": 0, "fetchStart": 237.85999999381602, "domainLookupStart": 237.85999999381602, "domainLookupEnd": 237.85999999381602, "connectStart": 237.85999999381602, "connectEnd": 237.85999999381602, "secureConnectionStart": 0, "requestStart": 243.38999995961785, "responseStart": 244.40500000491738, "responseEnd": 249.13499993272126, "transferSize": 0, "encodedBodySize": 29009, "decodedBodySize": 29009, "serverTiming": []}
应用场景一览
// DNS解析const dnsTime = navigationEntries.domainLookupEnd - navigationEntries.domainLookupStart;// 响应 + 响应工夫const totalTime = navigationEntries.responseEnd - navigationEntries.requestStart;// 缓存查找响应工夫const fetchTime = navigationEntries.responseEnd - navigationEntries.fetchStart;// 应用Service worker响应工夫let workerTime = 0;if (navigationEntries.workerStart > 0) {workerTime = navigationEntries.responseEnd - navigationEntries.workerStart;}// 收到第一个字节const ttfb = navigationEntries.responseStart - navigationEntries.requestStart;// 重定向工夫const redirectTime = navigationEntries.redirectEnd - navigationEntries.redirectStart;// 测量HTTP报头大小const headerSize = navigationEntries.transferSize - navigationEntries.encodedBodySize;// 测量资源加载工夫resourceListEntries.forEach(resource => { if (resource.initiatorType == 'img') { console.info(`Time taken to load ${resource.name}: `, resource.responseEnd - resource.startTime); }});// 获取单个资源指标const impResourceTime = performance.getEntriesByName("https://awebsite.com/imp-resource.png");
补充:间接应用 performance.timing
计算
正告: 该属性在 Navigation Timing Level 2 specification 中曾经被废除,请应用 PerformanceNavigationTiming 代替。尽管一些浏览器依然反对它,但兴许只是正筹备移除或出于兼容性而保留。
const timingInfo = window.performance.timing;// DNS解析,DNS查问耗时timingInfo.domainLookupEnd - timingInfo.domainLookupStart;// TCP连贯耗时timingInfo.connectEnd - timingInfo.connectStart;// 取得首字节消耗工夫,也叫TTFBtimingInfo.responseStart - timingInfo.navigationStart;// domReady工夫(与DomContentLoad事件对应)timingInfo.domContentLoadedEventStart - timingInfo.navigationStart;// DOM资源下载timingInfo.responseEnd - timingInfo.responseStart;// 筹备新页面工夫耗时timingInfo.fetchStart - timingInfo.navigationStart;// 重定向耗时timingInfo.redirectEnd - timingInfo.redirectStart;// Appcache 耗时timingInfo.domainLookupStart - timingInfo.fetchStart;// unload 前文档耗时timingInfo.unloadEventEnd - timingInfo.unloadEventStart;// request申请耗时timingInfo.responseEnd - timingInfo.requestStart;// 申请结束至DOM加载timingInfo.domInteractive - timingInfo.responseEnd;// 解释dom树耗时timingInfo.domComplete - timingInfo.domInteractive;// 从开始至load总耗时timingInfo.loadEventEnd - timingInfo.navigationStart;// 白屏工夫timingInfo.responseStart - timingInfo.fetchStart;// 首屏工夫timingInfo.domComplete - timingInfo.fetchStart;
参考:
Using the Performance API
How to practically use Performance API to measure performance
Performance.timing