使用 Javascript 的 window.performance.timing 计算页面加载时间

Posted

技术标签:

【中文标题】使用 Javascript 的 window.performance.timing 计算页面加载时间【英文标题】:Calculate Page Load Times using Javascript's window.performance.timing 【发布时间】:2020-01-23 01:22:57 【问题描述】:

我可以使用以下代码在 selenium 中计算页面加载时间:

代码:Selenium C#

using OpenQA.Selenium;
double requestStart = (long)((IjavascriptExecutor)CTest.Driver).ExecuteScript("return window.performance.timing.requestStart");
double domComplete = (long)((IJavaScriptExecutor)CTest.Driver).ExecuteScript("return window.performance.timing.domComplete");
var totaltime = domComplete - requestStart;

通过跟踪和错误,我能够确定 totaltime 上面的代码对应于下图中的值 Load。图像中的 Load 似乎总是与 DOMContentLoaded 变量的值相同。

问题

    为什么Finish 的值不一样? Finish 是什么?你如何使用 javascript 的 window.performance.timing 对象来计算它? 如何计算从在 Web 浏览器中输入 url(然后按回车键)到最终加载页面上所有内容的时间?

以下文档很好地描述了每个时间变量测量的内容 mozilla-developer timestamp variables,但是 chrome devtools 中的 Finish 值正在搅浑水。

:从 Chrome 的 Devtool (F12) Network 标签中提取性能信息


编辑

感谢@wOxxOm。我注意到 Finish 时间在我与网站交互时不断增加(转到网站中的不同页面),而 DOMContentLoadedLoad 从未改变在初始加载事件之后。这与您在回复中所说的相对应。 我按照您的建议改用以下代码:

double connectStart = (long)((IJavaScriptExecutor)CTest.Driver).ExecuteScript("return window.performance.timing.connectStart");
double loadEventEnd = (long)((IJavaScriptExecutor)CTest.Driver).ExecuteScript("return window.performance.timing.loadEventEnd");
double newMeasure = (loadEventEnd - connectStart) / 1000.0;

还开始研究 Chrome 77 中的 LCP 功能。

我确实还有一个问题

问题 2: 我最初认为 window.performance 对象中的值会在我点击一个链接(在网站上)时重新填充新值(时间),这会将我带到同一网站内的不同页面.然而,所有的 window.performance 值在网站初始加载后都不会改变(Chrome 的 devtool 网络窗口中的 DOMContentLoaded 和 Load 值在网站中移动时也不会改变)。

问题:为什么 window.performance 中的值从未改变?是因为这是一个 SPA(单页应用程序)吗?当我在不同的网站(旧)中点击时,我观察到 chrome devtool 的 DOMContentLoadedLoad 值,每次我进入该网站的新页面时,DOMContentLoaded 加载 时间更改为显示网站内每个页面的加载时间(通过单击该网站主菜单中的链接转到不同的页面)。

【问题讨论】:

1) "finish" 是根据 performance.getEntries() 中具有最新时间戳的请求计算得出的,但 entryType: "paint" 除外,2) 尝试 connectStart 而不是 requestStart 并减去它来自loadEventEnd,而不是domComplete。 3) 考虑改用LCP: largest-contentful-paint 指标。 @wOxxOm,感谢您的回答。测量网站中每个页面的页面负载的正确方法是什么?网站初始加载后,windows.performance 属性不会改变。如果我单击菜单链接转到其他页面,window.performance 属性不会更新以指示单击后需要多长时间才能在网站中显示其他网页。 客户端更新不会触发页面加载。所以你是对的,单页应用程序不会触发这些事件。 【参考方案1】:

为什么finished不等于domComplete - requestStart?

DOMContentLoaded 表示所有 DOM 内容都已加载,但 javascript 和图片仍在加载中

加载表示所有内容包括javascript和图片都已加载。如果您在触发此事件之前开始延迟加载图像和javascript,它将延迟此事件并减慢您的页面加载事件。 这会对您的谷歌灯塔分数产生负面影响

Finished在chrome开发工具中包含异步加载资源,在onload事件触发后可能会继续下载。一旦您的一个脚本开始通过 ajax 加载更多内容,完成时间就会增加。这个数字通常可以帮助您了解加载所有内容需要多长时间,包括延迟加载的图像、脚本等。可以而且应该在 load 事件之后加载,以改进您的页面的 SEO。

如何计算从浏览器输入网址到页面加载的时间?

搜索引擎关注的真正重要事件是load 事件。所以你并不真正关心finish 时间。您希望在触发此事件后将所有与您的应用第一次交互不需要的内容移动到延迟加载。

此外,您正在寻找navigationStart 而不是requestStart。在用户按下回车键 (navigationStart) 和实际执行请求 (requestStart) 之间会有一段时间。

W3C 规范:

导航开始

该属性必须在用户代理之后立即返回时间 完成提示卸载上一个文档。如果没有 上一个文档,这个属性必须返回当前的时间 文档已创建。

MDN 报价

performance.timing.navigationStart + performance.now() 将是 约等于 Date.now()

触发performance.now() onload 会告诉您到达那里需要多长时间。 但是 IE9 不支持它,并且某些浏览器会舍入结果。使用 Date.now() - window.performance.timing.navigationStart 可以得到更一致的结果,并且受 IE9 支持。

用于记录加载事件时间的 JS。

window.addEventListener('load', (event) => 
    console.log('All assets are loaded')
    console.log(Date.now() - window.performance.timing.navigationStart);
);

为什么 window.performance 值在初始加载后永远不会改变?

这与 SPA 页面有关。一旦加载了 DOM 和初始资产,其他所有内容都会异步加载。 SPA 的路由在前端处理,不会触发 chrome 开发工具中的新页面加载。即使手动重新加载页面,您也必须禁用网络选项卡中的“保留日志”选项才能获得新的性能值。

【讨论】:

以上是关于使用 Javascript 的 window.performance.timing 计算页面加载时间的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript(js)基础

JavaScript 在HTML中使用 JavaScript

javascript 使用javascript设置选定的值

javascript 使用Javascript的后备图像

javascript 使用Javascript的后备图像

javascript 使用