共计 5150 个字符,预计需要花费 13 分钟才能阅读完成。
从历史上看,咱们对客户端性能监控形式十分无限,而且还遇到了 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 entries
const 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;
// 取得首字节消耗工夫,也叫 TTFB
timingInfo.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