网页开发每天与浏览器相伴,一切展示来自于各类资源的加载。性能优化一定要有衡量指标,所谓“一切有据(数据)可循”,那么 PerformanceResourceTiming 则是你不容错过的一个官方 API。
我们从不生产官方文档,我们只做官方文档的搬运工。
本瓜倾情翻译、适量批注、莞尔小结,以供分享,烦请指正。撰文不易,点赞👍鼓励!
原文:https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming
用户延迟是 Web 应用程序的重要质量基准。尽管基于 JavaScript 的机制可以为应用程序中的用户延迟测量提供全面的工具,但在许多情况下,它们无法提供完整的端到端延迟剪影。本文档介绍了PerformanceResourceTiming 接口:允许 JavaScript 收集与文档资源相关的完整定时信息。
例如,以下演示了简单通过 JavaScript 来尝试获取资源所花费的时间的方法:
<!doctype html>
<html>
<head>
</head>
<body onload="loadResources()">
<script>
function loadResources()
{
var start = new Date().getTime();
var image1 = new Image();
var resourceTiming = function() {
var now = new Date().getTime();
var latency = now - start;
alert("End to end qresource fetch: " + latency);
};
image1.onload = resourceTiming;
image1.src = 'https://www.w3.org/Icons/w3c_main.png';
}
</script>
<img src="https://www.w3.org/Icons/w3c_home.png">
</body>
</html>
尽管此脚本可以获取资源所花费的时间,但是它不能分解在各个阶段花费的时间。此外,脚本无法轻松获取标记中描述的资源所花费的时间。
为了满足有关用户体验的完整信息的需求,本文档将介绍PerformanceResourceTiming。此接口允许 JavaScript 在应用程序中提供完整的客户端延迟测量。使用此接口,可以修改前面的示例以测量用户感知的资源加载时间。
<!doctype html>
<html>
<head>
</head>
<body onload="loadResources()">
<script>
function loadResources()
{
var image1 = new Image();
image1.onload = resourceTiming;
image1.src = 'https://www.w3.org/Icons/w3c_main.png';
}
function resourceTiming()
{
var resourceList = window.performance.getEntriesByType("resource");
for (i = 0; i < resourceList.length; i++)
{
if (resourceList[i].initiatorType == "img")
{
alert("End to end resource fetch: "+ resourceList[i].responseEnd - resourceList[i].startTime);
}
}
}
</script>
<img id="image0" src="https://www.w3.org/Icons/w3c_home.png">
</body>
</html>
除标记、指南,图表,示例和注释为非规范。本规范中的所有其他内容都是符合规范标准的。
关键字may,must,must not 和 should 的解释应如 RFC2119 中所述。
对于一部分算法命令应当做如下要求:(例如 “删除任何前导空格字符” 或 “返回 false 并中止这些步骤” )应使用关键字的含义(“必须”,“应”,“may” 等)来介绍算法。
一些对属性,方法或对象的一致性表述要求,应类比于对客户端的要求。
只要最终结果是等效的,可以用任何方式表述算法或特定步骤的一致性要求。(本规范中定义的算法旨在于遵循标准,而非标新立异。)
如 Web IDL 规范中所述,此规范中的 IDL 片段必须按照符合 IDL 片段的要求进行解释。WebIDL
有时使用 Foo 实际上是指接口的构造 “a Foo object”,而不是指精确意义上的“Foo 接口对象的实现”。
表述 DOM 用于表示Web 应用程序中的脚本的 API 集,并且不一定表示实际上的 Document 对象或 NodeDOM 规范中定义的任何其他对象。DOM
DOM 属性正在获取值时被称为“正在获取值”,分配新值时被称为“正在设置”。
由于 JavaScript 更为广为人知,因此表述 JavaScript 用于表示 ECMA262,而不是官方表述 ECMAScript。ECMA-262
在整个说明书中,术语 “ 资源 ” 用于指代元素和任何其他用户主动获取的。例如,资源可能源 自XMLHttpRequest 对象,HTML元素 HTML51(例如iframe,img,脚本,对象,嵌入和具有样式表链接类型的链接)以及SVG元素SVG11 。
表述“跨原点” 用于表示不同的原点。
表述“当前文档”是指与 Window 对象的最新 Document 对象关联的文档。
在整个工作过程中,自开始浏览文档HR-TIME-2 以来,所有时间值均以毫秒为单位。
术语“ 当前时间”是指从文档开始导航到当前时间点之间的毫秒数。
注意: 时间的定义基于高分辨率时间规范[ HR-TIME-2 ],并且与导航时间规范[ NAVIGATION-TIMING ]中使用的时间定义不同 ,后者的时间以自1970(UTC)年1月1日午夜起的毫秒数为单位。
PerformanceResourceTiming 接口有助于对可下载资源进行定时测量。例如,资源可能源 自XMLHttpRequest 对象,HTML元素 HTML51(例如 iframe,img,脚本,对象,嵌入和具有样式表链接类型的链接)以及SVG元素SVG11。
所有通过浏览 [HTML5] 或工作程序 [WORKERS] 上下文所获取的资源都必须在 Performance Timeline 中包含 PerformanceResourceTiming 对象,且不违反同源策略。从相关应用程序缓存中检索的资源或本地资源也必须在 Performance Timeline 中包括 PerformanceResourceTiming 对象。PERFORMANCE-TIMELINE-2
备注:该规范的未来版本可能需要包括中止的请求或不返回响应的请求。详见 issues 12
备注:开发者应注意 Issue 27:同源政策和遵守不跨域获取。
以下是特殊情况
例如: If a resource fetch is aborted because it failed a fetch precondition (e.g. mixed content, CORS restriction, CSP policy, etc), then this resource will not be included as a PerformanceResourceTiming object in the Performance Timeline.
本文关键之一
PerformanceResourceTiming 接口在 Performance Timeline 面板上有展现,并且其扩展 PerformanceEntry 接口有以下属性:
[Exposed=(Window)]
interface PerformanceResourceTiming : PerformanceEntry {
readonly attribute DOMString initiatorType;
readonly attribute DOMHighResTimeStamp redirectStart;
readonly attribute DOMHighResTimeStamp redirectEnd;
readonly attribute DOMHighResTimeStamp fetchStart;
readonly attribute DOMHighResTimeStamp domainLookupStart;
readonly attribute DOMHighResTimeStamp domainLookupEnd;
readonly attribute DOMHighResTimeStamp connectStart;
readonly attribute DOMHighResTimeStamp connectEnd;
readonly attribute DOMHighResTimeStamp secureConnectionStart;
readonly attribute DOMHighResTimeStamp requestStart;
readonly attribute DOMHighResTimeStamp responseStart;
readonly attribute DOMHighResTimeStamp responseEnd;
serializer = {inherit, attribute};
};
获取时,initiatorType 属性返回情况如下:
注意
这一小节结束:主要是 PerformanceEntry 的各个属性的各种返回值罗列情况。
这里不得不说人家文档就是规范。
且这里得挖个坑🕳,timing allow check algorithm,后续研究一下!
客户端可以选择在 Performance Timeline[ PERFORMANCE-TIMELINE-2 ]中限制 PerformanceResourceTiming 对象 。本节扩展了 Performance 界面,以允许控制更多 PerformanceResourceTiming 存储对象。
建议的最小 PerformanceResourceTiming 对象数是150,客户端可以更改,通过 setResourceTimingBufferSize 方法也可以更改此限制。
每个 ECMAScript 全局环境都具有:
注意 这里的缓冲与[ PERFORMANCE-TIMELINE-2 ]中定义的性能条目缓冲意义相同。
partial interface Performance {
void clearResourceTimings();
void setResourceTimingBufferSize(unsigned long maxSize);
attribute EventHandler onresourcetimingbufferfull;
};
Performance 对象是定义在 [HR-TIME-2]。
clearResourceTimings 方法实现过程:
setResourceTimingBufferSize 方法实现过程:
onresourcetimingbufferfull 属性是 resourcetimingbufferfull事件的事件处理程序。
要 在performance entry buffer 中添加 PerformanceResourceTiming 条目(新条目),需进行以下步骤:
前文提到较多的 timing allow check 在这里有解释
Timing-Allow-Origin HTTP 响应报头字段用于通信被允许看到,由于跨域限制属性的值为0。header 值由以下 ABNF [ RFC5234 ] 定义:
that would have been zero due to the cross-origin restrictions. The header's value is represented by the following ABNF [RFC5234]:
Timing-Allow-Origin = 1#(原点为空/通配符)
发送者可以生成多个 Timing-Allow-Origin header 字段。接收者可以通过按顺序将每个随后的字段值附加到组合的字段值上并用逗号分隔,来组合成一个包含多个 Timing-Allow-Origin header 字段。
timing allow check 算法,该算法检查是否一个资源的定时信息可以在当前文档共享,如下:
原理即是核心啦!
下图说明了从不同源获取资源时 PerformanceResourceTiming 接口定义的时序属性。带下划线的属性可能不可用。客户端可以在定时之间执行内部处理,这允许定时之间存在非标准间隔。
对于 performance timelime 包含的每个资源,执行以下步骤:
例子3 当持久连接 [ RFC7230 ]被启用,客户端可以首先尝试重新使用开放连接发送请求,而连接可以被异步地关闭。在这种情况下,connectStart,connectEnd 和 requestStart 应该表示收集的重新打开的连接的定时信息。
Monotonic clock(time) 字面意思是单调时间,实际上它指的是从某个点开始后(比如系统启动以后)流逝的时间
定时属性的值必须单调增加,以确保在获取资源时不会因调整系统时钟而使定时属性产生偏移量。任何两个按时间顺序记录的计时属性之间的差异绝不能为负。对于所有资源(包括子文档资源),浏览器必须在根文档导航开始时记录系统时钟,并根据测量从导航开始起经过的时间的单调时钟来定义后续的计时属性。
PerformanceResourceTiming 界面将资源的计时信息公开给已请求该资源的任何网页或工作者。为了限制对 PerformanceResourceTiming 接口的访问,默认情况下会强制执行相同的原始策略,并将某些属性设置为零,如在 跨域资源中所述。资源提供者可以通过添加 Timing-Allow-Origin HTTP 响应头来明确允许收集资源的所有时序信息,该请求头指定允许访问时序信息的域。
统计指纹识别是一种隐私问题,在这种情况下,恶意网站可能会通过测量第三方网站中缓存命中和资源丢失的时间来确定用户是否访问了第三方网站。尽管 PerformanceResourceTiming 接口提供了文档中资源的时序信息,但是跨域限制防止这种隐私问题比现今使用资源上的加载事件来测量时序以确定高速缓存命中和未命中的情况更为严重。
Though the PerformanceResourceTiming interface gives timing information for resources in a document, the cross-origin restrictions prevent making this privacy concern any worse than it is today using the load event on resources to measure timing to determine cache hits and misses.
不得不说官方文档写的真的严谨,自己在翻译的过程中,也是对自己编写文档能力是一种提升!
另结,以下指标在开发任一网站都尽量去关注,养成好习惯:
DNS查询耗时 :domainLookupEnd - domainLookupStart
TCP链接耗时 :connectEnd - connectStart
request请求耗时 :responseEnd - responseStart
解析dom树耗时 : domComplete - domInteractive
白屏时间 :responseStart - navigationStart
domready时间(用户可操作时间节点) :domContentLoadedEventEnd - navigationStart
onload时间(总下载时间) :loadEventEnd - navigationStart
期望:以后多接触前端监控(不限于性能监控)啦!