1. 简介
用户延迟是 Web 应用的一个重要质量基准。虽然基于 JavaScript 的机制可以为应用内的用户延迟测量提供全面的检测,但在许多情况下,它们无法提供完整的端到端延迟图景。本文档引入了 PerformanceResourceTiming 接口,允许 JavaScript 机制收集与文档上资源相关的完整计时信息。导航计时 2 [NAVIGATION-TIMING-2] 扩展了此规范,以提供与导航相关的额外计时信息。
例如,以下 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 resource fetch: " + latency); }; image1. onload= resourceTiming; image1. src= 'https://w3org.cn/Icons/w3c_main.png' ; } </ script > < img src = "https://w3org.cn/Icons/w3c_home.png" > </ body > </ html >
虽然此脚本可以测量获取资源的时间,但它无法细分在各个阶段所花费的时间。此外,脚本无法轻易测量获取标记语言中所述资源所需的时间。
为了解决对完整用户体验信息的需求,本文档引入了 PerformanceResourceTiming 接口。此接口允许 JavaScript 机制在应用内提供完整的客户端延迟测量。利用此接口,可以修改前面的示例,以测量用户感知的资源加载时间。
以下脚本计算了获取页面上每个资源所需的时间,甚至包括那些在标记语言中定义的资源。此示例假设该页面托管在 https://w3org.cn 上。人们还可以使用 PerformanceResourceTiming 接口进一步测量获取资源每个阶段所花费的时间。
<!doctype html> < html > < head > </ head > < body onload = "loadResources()" > < script > function loadResources() { var image1= new Image(); image1. onload= resourceTiming; image1. src= 'https://w3org.cn/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://w3org.cn/Icons/w3c_home.png" > </ body > </ html >
2. 术语
构造“一个 Foo 对象”(其中 Foo 实际上是一个接口)有时被使用,以代替更准确的“一个实现 Foo 接口的对象”。
在整项工作中,所有时间值均以文档导航开始以来的毫秒数进行测量 [HR-TIME]。例如,文档导航的开始发生在 0 时刻。
此时间定义基于高分辨率时间规范 [HR-TIME],且与导航计时规范 [NAVIGATION-TIMING-2] 中使用的时间定义不同,后者是以 1970 年 1 月 1 日午夜(UTC)以来的毫秒数测量时间。
3. 资源计时
3.1. 简介
PerformanceResourceTiming 接口有助于对 获取 的 http(s) 资源进行计时测量。例如,此接口可用于 XMLHttpRequest 对象 [XHR]、HTML 元素 [HTML](例如 iframe、img、script、object、embed 以及链接类型为 stylesheet 的 link)、SVG 元素 [SVG11](例如 svg)以及 EventSource。
3.2. PerformanceResourceTiming 接口中包含的资源
本节是非规范性的。
由非空 客户端 获取 的资源 请求 将作为 PerformanceResourceTiming 对象包含在 客户端 的 全局对象 的 性能时间线 中,除非在 获取过程 中被排除在时间线之外。从 HTTP 缓存中检索的资源将作为 PerformanceResourceTiming 对象包含在 性能时间线 中。已发起但随后中止(例如由于网络错误)的 获取 资源将作为 PerformanceResourceTiming 对象包含在 性能时间线 中,并附带其开始和结束时间。
示例
- 如果相同的规范 URL 被用作两个 HTML
IMG元素的src属性,则由第一个 HTMLIMG元素发起的资源 获取 将作为PerformanceResourceTiming对象包含在 性能时间线 中。用户代理可能不会为第二个 HTMLIMG元素重新请求该 URL,而是使用它为第一个 HTMLIMG元素发起的现有下载。在这种情况下,第一个IMG元素对资源的 获取 将是 性能时间线 中出现的唯一一次。 - 如果 HTML
IMG元素的src属性通过脚本更改,则原始资源的 获取 以及新 URL 的 获取 都将作为PerformanceResourceTiming对象包含在 性能时间线 中。 - 如果 HTML
IFRAME元素通过标记语言添加且未指定src属性,用户代理可能会为IFRAME加载about:blank文档。如果随后通过脚本动态更改src属性,用户代理可能会 获取IFRAME的新 URL 资源。在这种情况下,只有新 URL 的 获取 会作为PerformanceResourceTiming对象包含在 性能时间线 中。 - 如果为相同的规范 URL 生成了两次
XMLHttpRequest,则该资源的两次 获取 都将作为PerformanceResourceTiming对象包含在 性能时间线 中。这是因为第二个XMLHttpRequest的资源 获取 无法重用为第一个XMLHttpRequest发起的下载。 - 如果页面中包含 HTML
IFRAME元素,则仅有IFRAME的src属性请求的资源作为PerformanceResourceTiming对象包含在 性能时间线 中。由IFRAME文档请求的子资源将包含在IFRAME文档的 性能时间线 中,而不是父文档的 性能时间线 中。 - 如果 HTML
IMG元素具有data: URI作为其源 [RFC2397],则此资源将不会作为PerformanceResourceTiming对象包含在 性能时间线 中。PerformanceResourceTiming条目仅针对 http(s) 资源报告。 - 如果由于网络错误(例如 DNS、TCP 或 TLS 错误)导致资源 获取 中止,则该获取将作为
PerformanceResourceTiming对象包含在 性能时间线 中,并且仅设置startTime、fetchStart、duration和responseEnd。 - 如果由于未通过获取前提条件(例如混合内容、CORS 限制、CSP 策略等)导致资源 获取 中止,则此资源将不会作为
PerformanceResourceTiming对象包含在 性能时间线 中。
3.3. PerformanceResourceTiming 接口
[Exposed =(Window ,Worker )]interface :PerformanceResourceTiming PerformanceEntry {readonly attribute DOMString ;initiatorType readonly attribute DOMString ;deliveryType readonly attribute ByteString ;nextHopProtocol readonly attribute DOMHighResTimeStamp ;workerStart 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 ;finalResponseHeadersStart readonly attribute DOMHighResTimeStamp ;firstInterimResponseStart readonly attribute DOMHighResTimeStamp ;responseStart readonly attribute DOMHighResTimeStamp ;responseEnd readonly attribute DOMHighResTimeStamp ;workerRouterEvaluationStart readonly attribute DOMHighResTimeStamp ;workerCacheLookupStart readonly attribute DOMString ;workerMatchedRouterSource readonly attribute DOMString ;workerFinalRouterSource readonly attribute unsigned long long ;transferSize readonly attribute unsigned long long ;encodedBodySize readonly attribute unsigned long long ;decodedBodySize readonly attribute unsigned short ;responseStatus readonly attribute RenderBlockingStatusType ;renderBlockingStatus readonly attribute DOMString ;contentType readonly attribute DOMString ; [contentEncoding Default ]object (); };toJSON
一个 PerformanceResourceTiming 具有一个关联的 DOMString 发起者类型。
一个 PerformanceResourceTiming 具有一个关联的 DOMString 交付类型。
一个 PerformanceResourceTiming 具有一个关联的 DOMString 请求 URL。
一个 PerformanceResourceTiming 具有一个关联的 DOMString 缓存模式(空字符串、“local”或“validated”)。
一个 PerformanceResourceTiming 具有一个关联的 获取计时信息 计时信息。
一个 PerformanceResourceTiming 具有一个关联的 响应体信息 资源信息。
一个 PerformanceResourceTiming 具有一个关联的 状态 响应状态。
一个 PerformanceResourceTiming 具有一个关联的 RenderBlockingStatusType 渲染阻塞状态。
当调用 toJSON 时,对 PerformanceResourceTiming 运行 默认 toJSON 步骤。
initiatorType getter 步骤是返回 this 的 发起者类型。
initiatorType 返回以下值之一
-
"navigation",如果请求是 导航请求; -
"body",如果请求是处理body元素的background属性(已过时)的结果。 -
"css",如果请求是处理 CSS url() 指令(例如@import url()或background: url())的结果; [CSS-VALUES]注意:使用 CSS
@font-face指定的字体资源的请求是处理 CSS 指令的结果。因此,此字体资源的initiatorType为"css"。 -
"script",如果请求是加载任何 脚本(经典script、模块脚本 或Worker)的结果。 -
"xmlhttprequest",如果请求是处理XMLHttpRequest的结果; -
"font",如果请求是处理字体得到的结果。当字体请求后续资源时(例如使用增量字体传输 [INCREMENTAL_FONT_TRANSFER] 时),可能会发生这种情况。 -
"fetch",如果请求是处理fetch()方法的结果; -
"beacon",如果请求是处理sendBeacon()方法的结果; [BEACON] -
"video",如果请求是处理video元素的poster或src的结果。 -
"audio",如果请求是处理audio元素的src的结果。 -
"track",如果请求是处理track元素的src的结果。 -
"img",如果请求是处理img元素的src或srcset的结果。 -
"image",如果请求是处理 image 元素的结果。 [SVG2] -
"input",如果请求是处理input元素(其type为 image)的结果。 -
"ping",如果请求是处理a元素的ping的结果。 -
"iframe",如果请求是处理iframe的src的结果。 -
"frame",如果请求是加载frame的结果。 -
"embed",如果请求是处理embed元素的src的结果。 -
"link",如果请求是处理link元素的结果。 -
"object",如果请求是处理object元素的结果。 -
"early-hints",如果请求是处理 Early Hints [EARLY_HINTS] 响应的结果。 -
"other",如果不匹配上述任何条件。
initiatorType 的设置是在报告资源计时条目的不同位置完成的,例如 获取 标准。
deliveryType getter 步骤是返回 this 的 交付类型。
deliveryType 返回以下值之一
-
"cache",如果 缓存模式 不是空字符串。 - 空字符串
"",如果不匹配上述任何条件。
预计未来对本规范的更新将对其进行扩展,例如描述消耗预加载资源和预取导航请求。
workerStart getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 最终 Service Worker 开始时间,以及 this 的 相关全局对象。有关更多信息,请参阅 HTTP 获取。
redirectStart getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 重定向开始时间,以及 this 的 相关全局对象。有关更多信息,请参阅 HTTP 重定向获取。
redirectEnd getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 重定向结束时间,以及 this 的 相关全局对象。有关更多信息,请参阅 HTTP 重定向获取。
fetchStart getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 重定向后开始时间,以及 this 的 相关全局对象。有关更多信息,请参阅 HTTP 获取。
domainLookupStart getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 最终连接计时信息 的 域名查找开始时间,以及 this 的 相关全局对象。有关更多信息,请参阅 记录连接计时信息。
domainLookupEnd getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 最终连接计时信息 的 域名查找结束时间,以及 this 的 相关全局对象。有关更多信息,请参阅 记录连接计时信息。
connectStart getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 最终连接计时信息 的 连接开始时间,以及 this 的 相关全局对象。有关更多信息,请参阅 记录连接计时信息。
connectEnd getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 最终连接计时信息 的 连接结束时间,以及 this 的 相关全局对象。有关更多信息,请参阅 记录连接计时信息。
secureConnectionStart getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 最终连接计时信息 的 安全连接开始时间,以及 this 的 相关全局对象。有关更多信息,请参阅 记录连接计时信息。
nextHopProtocol getter 步骤是 同构解码 this 的 计时信息 的 最终连接计时信息 的 ALPN 协商协议。有关更多信息,请参阅 记录连接计时信息。
问题 221 建议删除对 nextHopProtocol 的支持,因为它可能会泄露有关用户网络配置的详细信息。
requestStart getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 最终网络请求开始时间,以及 this 的 相关全局对象。有关更多信息,请参阅 HTTP 获取。
firstInterimResponseStart getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 首次临时网络响应开始时间,以及 this 的 相关全局对象。有关更多信息,请参阅 HTTP 获取。
finalResponseHeadersStart getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 最终网络响应开始时间,以及 this 的 相关全局对象。有关更多信息,请参阅 HTTP 获取。
responseStart getter 步骤是:如果 this 的 firstInterimResponseStart 不为 0,则返回它;否则返回 this 的 finalResponseHeadersStart。
responseEnd getter 步骤是 转换获取时间戳 为 this 的 计时信息 的 结束时间,以及 this 的 相关全局对象。有关更多信息,请参阅 获取。
encodedBodySize getter 步骤是返回 this 的 资源信息 的 编码大小。
decodedBodySize getter 步骤是返回 this 的 资源信息 的 解码大小。
transferSize getter 步骤如下:
-
添加到
transferSize的常量数字取代了公开 HTTP 标头的总字节大小,因为这可能会公开某些 Cookie 的存在。请参阅 此问题。
responseStatus getter 步骤是返回 this 的 响应状态。
responseStatus 在 获取 (Fetch) 中确定。对于跨源 no-cors 请求,它将为 0,因为响应将是 不透明的过滤响应。
contentType getter 步骤是返回 this 的 资源信息 的 内容类型。
contentEncoding getter 步骤是返回 this 的 资源信息 的 内容编码。
renderBlockingStatus getter 步骤是:如果 this 的 计时信息 的 渲染阻塞 为真,则返回 阻塞;否则返回 非阻塞。
workerRouterEvaluationStart getter 步骤是返回 this 的 计时信息 的 Service Worker 计时信息 的 Worker 路由评估开始。
workerCacheLookupStart getter 步骤是返回 this 的 计时信息 的 Service Worker 计时信息 的 Worker 缓存查找开始。
workerMatchedRouterSource getter 步骤是返回 this 的 计时信息 的 Service Worker 计时信息 的 Worker 匹配路由源。
workerFinalRouterSource getter 步骤是返回 this 的 计时信息 的 Service Worker 计时信息 的 Worker 最终路由源。
实现 PerformanceResourceTiming 的用户代理需要将 "resource" 包含在 supportedEntryTypes 中。这允许开发者检测对资源计时的支持。
3.3.1. RenderBlockingStatusType 枚举
enum {RenderBlockingStatusType ,"blocking" };"non-blocking"
各值的定义如下:
- blocking
- 该资源可能会阻塞渲染。
- non-blocking
- 该资源不会阻塞渲染。
3.4. Performance 接口的扩展
用户代理可以选择限制作为 PerformanceResourceTiming 对象包含在 性能时间线 [PERFORMANCE-TIMELINE-2] 中的资源数量。本节扩展了 Performance 接口,以允许控制存储的 PerformanceResourceTiming 对象的数量。
建议的 PerformanceResourceTiming 对象最小数量为 250,尽管用户代理可能会更改此数量。setResourceTimingBufferSize 可以被调用以请求更改此限制。
每个 ECMAScript 全局环境 具有:
- 一个 资源计时缓冲区大小限制,初始应为 250 或更大。
- 一个 资源计时缓冲区当前大小,初始为 0。
- 一个 资源计时缓冲区已满事件挂起标志,初始为 false。
- 一个 资源计时二级缓冲区当前大小,初始为 0。
- 一个 资源计时二级缓冲区,用于存储初始为空的
PerformanceResourceTiming对象。
partial interface Performance {undefined ();clearResourceTimings undefined (setResourceTimingBufferSize unsigned long );maxSize attribute EventHandler ; };onresourcetimingbufferfull
Performance 接口定义在 [HR-TIME] 中。
方法 clearResourceTimings 运行以下步骤:
- 移除 性能条目缓冲区 中的所有
PerformanceResourceTiming对象。 - 将 资源计时缓冲区当前大小 设置为 0。
方法 setResourceTimingBufferSize 运行以下步骤:
- 将 资源计时缓冲区大小限制 设置为 maxSize 参数。如果 maxSize 参数小于 资源计时缓冲区当前大小,则不得从 性能条目缓冲区 中移除任何
PerformanceResourceTiming对象。
属性 onresourcetimingbufferfull 是下方描述的 resourcetimingbufferfull 事件的事件处理程序。
要检查是否可以 添加资源计时条目,请运行以下步骤:
- 如果 资源计时缓冲区当前大小 小于 资源计时缓冲区大小限制,则返回 true。
- 返回 false。
要将 添加 PerformanceResourceTiming 条目 新条目 到 性能条目缓冲区,请运行以下步骤:
- 如果 可以添加资源计时条目 返回 true 且 资源计时缓冲区已满事件挂起标志 为 false,请运行以下子步骤:
- 将 新条目 添加到 性能条目缓冲区。
- 将 资源计时缓冲区当前大小 增加 1。
- 返回。
- 如果 资源计时缓冲区已满事件挂起标志 为 false,请运行以下子步骤:
- 将 资源计时缓冲区已满事件挂起标志 设置为 true。
- 在任务队列中排队一个任务,该任务位于 性能时间线任务源上,以运行 触发缓冲区已满事件。
- 将 新条目 添加到 资源计时二级缓冲区。
- 将 资源计时二级缓冲区当前大小 增加 1。
要 复制二级缓冲区,请运行以下步骤:
- 当 资源计时二级缓冲区 不为空且 可以添加资源计时条目 返回 true 时,请运行以下子步骤:
- 令 条目 为 资源计时二级缓冲区 中最旧的
PerformanceResourceTiming。 - 将 条目 添加到 性能条目缓冲区 的末尾。
- 将 资源计时缓冲区当前大小 增加 1。
- 从 资源计时二级缓冲区 中移除 条目。
- 将 资源计时二级缓冲区当前大小 减少 1。
- 令 条目 为 资源计时二级缓冲区 中最旧的
要 触发缓冲区已满事件,请运行以下步骤:
- 当 资源计时二级缓冲区 不为空时,请运行以下子步骤:
- 令 超出条目数量前 为 资源计时二级缓冲区当前大小。
- 如果 可以添加资源计时条目 返回 false,则在
Performance对象上 触发一个名为resourcetimingbufferfull的事件。 - 运行 复制二级缓冲区。
- 令 超出条目数量后 为 资源计时二级缓冲区当前大小。
- 如果 超出条目数量前 小于或等于 超出条目数量后,则从 资源计时二级缓冲区 中移除所有条目,将 资源计时二级缓冲区当前大小 设置为 0,并中止这些步骤。
- 将 资源计时缓冲区已满事件挂起标志 设置为 false。
这意味着如果
resourcetimingbufferfull事件处理程序在缓冲区中添加的空间没有它向其中添加的资源多,多出的条目将从缓冲区中丢弃。开发者需要确保resourcetimingbufferfull事件处理程序调用clearResourceTimings或充分扩展缓冲区(通过调用setResourceTimingBufferSize)。
3.5. 跨源资源
3.5.1. 简介
如 获取 (Fetch) 中详述,跨源资源的请求作为 PerformanceResourceTiming 对象包含在 性能时间线 中。
如果跨源资源的 计时允许检查 算法失败,则该条目将成为 不透明条目。此类条目的大多数属性都会被掩盖,以防止泄露原本未暴露的跨源数据。因此,对于 不透明条目,以下属性将始终返回零或空字符串:redirectStart、redirectEnd、workerStart、domainLookupStart、domainLookupEnd、connectStart、connectEnd、requestStart、firstInterimResponseStart、finalResponseHeadersStart、responseStart、secureConnectionStart 和 nextHopProtocol。
当响应为 CORS 跨源 时,某些属性(例如 contentType、encodedBodySize 和 decodedBodySize)会被设置为零(或 contentType 的空字符串)。
transferSize 同时受 计时允许检查 和 CORS 跨源 状态的影响。
对于使用 respondWith() 的 Service Worker 处理的请求,报告的计时数据反映的是客户端与 Service Worker 之间的交互,而不是 Service Worker 自身的内部网络活动。例如,Service Worker 可能会用跨源响应回复同源请求,反之亦然,或者对两者返回缓存或合成响应。鉴于此,从 Service Worker 转发的资源并不能说明获取资源的完整情况,也不会经过 计时允许检查。要获取这些获取的完整信息,可以检查 Service Worker 自身的性能时间线。 [SERVICE-WORKERS]
有关更多详细信息,请参阅 HTTP 获取 #4 - 计时允许检查 仅在 Service Worker 没有响应时执行。此外,在 respondWith() 算法中克隆的 响应 不携带内部获取的 获取计时信息,因为该信息附加在获取上,而不是 响应 上。
3.5.2. Timing-Allow-Origin 响应头
服务器端应用可以返回 Timing-Allow-Origin HTTP 响应头,允许用户代理向指定的文档源完整公开由于跨源限制而本应为零的属性值。
Timing-Allow-Origin HTTP 响应头字段可用于传达一个策略,指示允许哪些源查看由于跨源限制而本应为零的属性值。该标头的值由以下 ABNF [RFC5234] 表示(使用 列表扩展,[RFC9110])
Timing-Allow-Origin = 1#( origin-or-null / wildcard )
发送者可以生成多个 Timing-Allow-Origin 标头字段。接收者可以通过将每个后续字段值附加到组合字段值中(以逗号分隔)来组合多个 Timing-Allow-Origin 标头字段。
即使存在 Timing-Allow-Origin HTTP 响应头字段,用户代理仍可能强制执行跨源限制并将 transferSize、encodedBodySize 和 decodedBodySize 属性设置为零。如果这样做,它也可能将 deliveryType 设置为 ""。
Timing-Allow-Origin 标头在 获取 (FETCH) 中进行处理,以相应地计算属性。
Timing-Allow-Origin 标头可能会作为缓存响应的一部分到达。根据 RFC 7234,在缓存重新验证的情况下,标头的值可能来自重新验证响应,或者如果该处不存在,则来自原始缓存资源。
3.5.3. IANA 注意事项
本节将 Timing-Allow-Origin 注册为 临时消息头。
- 头字段名称
-
Timing-Allow-Origin
- 适用协议
- http
- 状态
- provisional
- 作者/变更控制者
- W3C
- 规范文档
- § 3.5.2 Timing-Allow-Origin 响应头
3.6. 资源计时属性
本节是非规范性的。
下图说明了 PerformanceResourceTiming 接口定义的计时属性。括号中的属性在 获取 跨源资源时可能不可用。用户代理可以在计时之间执行内部处理,这允许在计时之间存在非规范性的间隔。
PerformanceResourceTiming 接口定义的计时属性。括号中的属性表示如果资源未通过 计时允许检查 算法,它们可能不可用。4. 创建资源计时条目
要给定一个 获取计时信息 timingInfo、一个 DOMString requestedURL、一个 DOMString initiatorType、一个 全局对象 global、一个字符串 cacheMode、一个 响应体信息 bodyInfo、一个 状态 responseStatus 以及一个可选的 字符串 deliveryType(默认为空字符串),标记资源计时,请执行以下步骤:
- 在 global 的 领域 (realm) 中创建一个
PerformanceResourceTiming对象 entry。 - 设置资源计时条目 为 entry,给定 initiatorType、requestedURL、timingInfo、cacheMode、bodyInfo、responseStatus 和 deliveryType。
- 排队一个 PerformanceEntry entry。
- 添加 entry 到 global 的 性能条目缓冲区。
要给定 DOMString initiatorType、DOMString requestedURL、获取计时信息 timingInfo、一个 DOMString cacheMode、一个 响应体信息 bodyInfo、一个 状态 responseStatus 以及一个可选的 DOMString deliveryType(默认为空字符串),设置资源计时条目 为 PerformanceResourceTiming entry,请执行以下步骤:
- 断言 cacheMode 为空字符串、“
local”或“validated”。 - 令 global 为 entry 的 相关全局对象。
- 初始化 entry,给定结果 转换 timingInfo 的 开始时间(给定 global、"
resource"、requestedURL)以及结果 转换 timingInfo 的 结束时间(给定 global)。 - 将 entry 的 发起者类型 设置为 initiatorType。
- 将 entry 的 请求 URL 设置为 requestedURL。
- 将 entry 的 计时信息 设置为 timingInfo。
- 将 entry 的 资源信息 设置为 bodyInfo。
- 将 entry 的 缓存模式 设置为 cacheMode。
- 将 entry 的 响应状态 设置为 responseStatus。
- 如果 deliveryType 为空字符串且 cacheMode 不为空,则将 deliveryType 设置为 "
cache"。 - 将 entry 的 交付类型 设置为 deliveryType。
对于给定的 DOMHighResTimeStamp ts 和 全局对象 global,转换获取时间戳(convert fetch timestamp) 的步骤如下:
- 如果 ts 为零,则返回零。
- 否则,返回针对 ts 和 global 的 相对高分辨率粗略时间(relative high resolution coarse time)。
5. 安全性考量
PerformanceResourceTiming 接口向任何请求了资源的网页或 worker 公开该资源的计时信息。为了限制对 PerformanceResourceTiming 接口的访问,默认强制执行 同源策略,并将某些属性设为零,详见 HTTP 获取(HTTP fetch) 的描述。资源提供方可以通过添加 Timing-Allow-Origin HTTP 响应头来显式允许收集资源的所有计时信息,该响应头指定了被允许访问此计时信息的域。
6. 隐私考量
统计指纹识别是一个隐私问题,恶意网站可能会通过测量第三方网站资源的缓存命中和未命中时间,来确定用户是否访问过该第三方网站。尽管 PerformanceResourceTiming 接口提供了文档中资源的计时信息,但资源上的 load 事件本已能够以有限的方式测量计时以确定缓存命中和未命中,且 HTTP 获取 中的跨源限制防止了任何额外信息的泄露。
7. 致谢
感谢 Anne Van Kesteren、Annie Sullivan、Arvind Jain、Boris Zbarsky、Darin Fisher、Jason Weber、Jonas Sicking、James Simonsen、Karen Anderson、Kyle Scholz、Nic Jansma、Philippe Le Hegaret、Sigbjørn Vik、Steve Souders、Todd Reifsteck、Tony Gentilcore、William Chan 以及 Alex Christensen 对这项工作的贡献。