如何使用 Puppeteer 计算页面完全加载时间?

2023-11-30

我试图使用 Node 中的 puppeteer 在几秒钟内获得页面完全加载时间,为此我对 API 和其他问题进行了一些研究,并创建了以下代码:

/* First Configuration */
    puppeteer.launch({
            defaultViewport: { width: 1600, height: 800 }
      }).then(async browser => {
        const page = await browser.newPage();
    await page.setCacheEnabled(false);
        await page.goto('https://stackoverflow.com', {waitUntil: 'networkidle0'});

        /* Get Page Metrics */

        const perf = await page.metrics();
        console.log(JSON.stringify(perf));

        /* Get Page Evaluate */

        const timing = await page.evaluate(() => {
            const result = {};
            for (const key of Object.keys(window.performance.timing.__proto__))
                result[key] = window.performance.timing[key];
            return result;
        });
        console.log(JSON.stringify(timing));

        /* Show Results on Browser Close */

        await browser.close().then(() => {

    var fullyLoadEvaluate = (timing.loadEventEnd - timing.navigationStart);
        console.log('Fully Load Time (Page Evaluate): ' + fullyLoadEvaluate);

        var fullyLoadMetrics = (perf.LayoutDuration + perf.RecalcStyleDuration + perf.ScriptDuration + perf.TaskDuration);
        console.log('Fully Load Time (Page Metrics): ' + fullyLoadMetrics);

        /* Send Response to Server */
        res.send('Check The Console');
        });

      });

基本上我使用两个代码来返回指标,其中之一是page.metrics()返回以下数据:

{"Timestamp":961736.600171,"Documents":8,"Frames":4,"JSEventListeners":375,"Nodes":8654,"LayoutCount":27,"RecalcStyleCount":31,"LayoutDuration":0.705517,"RecalcStyleDuration":0.144379,"ScriptDuration":0.527385,"TaskDuration":1.812213,"JSHeapUsedSize":11082496,"JSHeapTotalSize":20344832}

还有最后一张page.evaluate(),返回以下内容:

{"navigationStart":1556722407938,"unloadEventStart":0,"unloadEventEnd":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1556722407938,"domainLookupStart":1556722408247,"domainLookupEnd":1556722408548,"connectStart":1556722408548,"connectEnd":1556722408737,"secureConnectionStart":1556722408574,"requestStart":1556722408738,"responseStart":1556722408940,"responseEnd":1556722409087,"domLoading":1556722408957,"domInteractive":1556722409995,"domContentLoadedEventStart":1556722409995,"domContentLoadedEventEnd":1556722410190,"domComplete":1556722412584,"loadEventStart":1556722412584,"loadEventEnd":1556722412589,"toJSON":{}}

在我的示例中,我正在测试该网站https://stackoverflow.com. Like 网页测试.org and getmetrix.com,我试图得到页面完全加载时间.

我知道这种值不一致,但我想知道我计算的值是否正确,两个结果似乎哪个更正确?Fully Load Time (Page Evaluate) or Fully Load Time (Page Metrics) ?


您可以使用page.metrics()比较两个时间点(例如之前和之后page.goto). The page.evaluate方法来读取数据performanceAPI也是一个不错的选择。正如我在评论中已经指出的那样,没有定义什么应该被视为“整页加载”。两种方法都是有效的。

甚至更复杂

人们可能会考虑加载页面的许多事情:

  • DOMContentLoaded事件被触发
  • Load事件被触发
  • 从导航开始到文档中嵌入所有资源(例如加载图像)所需的时间
  • 从导航开始到所有资源加载完毕所需的时间
  • 直到没有更多正在进行的网络请求为止的时间。
  • ...

您还必须考虑是否希望网络相关阶段(例如 DNS)成为测量的一部分。以下是一个示例请求(使用 Chrome DevTools Network 选项卡生成),显示单个请求可能有多复杂:

Chrome DevTools Network Timing

还有一个document解释每个阶段。

简单的方法

测量加载时间的最简单方法就是在导航开始时开始测量,并在页面加载后停止测量。这可以这样做:

const t1 = Date.now();
await page.goto('https://example.com');
const diff1 = Date.now() - t1;
console.log(`Time: ${diff1}ms`);

请注意,还有其他 API(page.metrics, process.hrtime, perf_hooks)以获得更精确的时间戳。

您还可以将选项传递给page.goto函数将承诺的解析更改为类似这样的内容(引自文档):

当网络连接数不超过 0 且持续时间至少 500 毫秒时,认为导航完成

为此,您必须使用该设置networkidle0:

await page.goto('https://example.com', { waitUntil: 'networkidle0' });

您还可以使用上面链接的文档中的其他事件。

更复杂:使用性能 API

为了获得更精确的结果,您可以使用性能API正如您已经在代码中所做的那样。而不是通过原型window.performance您还可以使用以下功能performance.getEntries() or performance.toJSON()像这样:

const perfData = await page.evaluate(() =>
    JSON.stringify(performance.toJSON(), null, 2)
);

这样,您将获得如下所示的数据:

{
  "timeOrigin": 1556727036740.113,
  "timing": {
    "navigationStart": 1556727036740,
    "unloadEventStart": 0,
    "unloadEventEnd": 0,
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 1556727037227,
    "domainLookupStart": 1556727037230,
    "domainLookupEnd": 1556727037280,
    "connectStart": 1556727037280,
    "connectEnd": 1556727037348,
    "secureConnectionStart": 1556727037295,
    "requestStart": 1556727037349,
    "responseStart": 1556727037548,
    "responseEnd": 1556727037805,
    "domLoading": 1556727037566,
    "domInteractive": 1556727038555,
    "domContentLoadedEventStart": 1556727038555,
    "domContentLoadedEventEnd": 1556727038570,
    "domComplete": 1556727039073,
    "loadEventStart": 1556727039073,
    "loadEventEnd": 1556727039085
  },
  "navigation": {
    "type": 0,
    "redirectCount": 0
  }
}

所以如果你想知道从navigationStart to loadEventStart您从一个值中减去另一个值(例如1556727039073 - 1556727036740 = 2333 ms).

那么该选择哪一个呢?

这取决于您的决定。一般来说,使用Load事件作为起点。等待所有请求完成实际上可能永远不会发生,因为后台不断加载资源。使用networkidle2 as waitUntil option如果您不想使用加载事件,可能是一种替代方法。

然而,最终,这取决于您的用例使用哪个指标。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Puppeteer 计算页面完全加载时间? 的相关文章

  • 如何精确缩放已翻译的d3地图

    我有一张已翻译的地图 以使其正确适合画布 我正在尝试实现一种缩放它的方法 它确实有效 但是当您放大时它会远离中心 而不是以鼠标甚至画布为中心 这是我的代码 function map data total views var xy d3 ge
  • Javascript 无法正确排序 DECIMAL 数字

    我有一些代码可以按字母顺序对名称进行排序 我遇到的问题是它处理小数的方式 它对名称进行排序 如下所示 我宁愿它按数字递增 DOG 1 0510 DOG 1 1031 DOG 11 1792 DOG 12 0920 DOG 12 1170 D
  • 无法根据TypeOrm中的外键过滤数据

    我使用 Nest Js PostgresQl 和 Typeorm 我在 typeorm 中有这两个实体 export class Meta PrimaryGeneratedColumn name metaId metaId number C
  • jQuery数据表设置列设计和成功回调中的值

    我为我的数据表编写了以下代码 它用我的数据库中的内容填充表 如下所示 if datatable null datatable destroy datatable tableProducts DataTable pageLength 50 b
  • 通过 Javascript 更改 Webkit 属性?

    请帮助我 可能是因为我对 CSS 动画和 Javascript 相当陌生 但我使用的代码应该更改它的属性 当我运行代码时 它会执行代码中的所有其他操作 除了更改所需 div 的 CSS 属性 我已经尝试了所有这四种方法 但似乎都不起作用 它
  • 如何显示/隐藏jsf组件

    在我的一个 JSF 应用程序中 顶部的标题部分包含 selectOneMenu 底部的内容部分显示过滤器组件 默认情况下 应用程序首先在顶部显示 selectOneMenu 数据 在底部显示相应的 Filter 信息 如果用户选择不同的se
  • “move(-1)”作为 AngularJS 表达式有什么问题吗?

    我收到此错误 parse ueoe Unexpected end of expression move 从这段代码来看
  • 使用 jquery 更改锚文本和图标

    我有一个隐藏或显示 div 的锚标记 但我无法更改它的文本和图标 如何更改文本和图标标签 因为目前它将图标标签解析为常规文本 锚标记 a class collapse info btn i class icon arrow up icon
  • 无法从 bash 脚本使用 nvm

    我正在尝试编写一个 shell 脚本来自动设置我的开发环境 安装 python nvm node mongo 等 我正在使用 nvm 来安装 Node js 它告诉您关闭并重新打开终端以开始使用 nmv 命令 我尝试获取 bashrc 和
  • 使用淘汰赛动态显示/隐藏元素

    我有一个表 有四列 即代码 名称 数量和价格 其中 我想动态更改数量列的内容 元素 通常 它应该显示其中显示数量的元素 当用户单击元素时 我想显示该元素 以便用户可以编辑数量 我正在尝试按照 示例2 来实现淘汰赛文档链接 http knoc
  • 如何在socket.io Nodejs服务器上列出房间

    在问题取得进展后如何创建socket io多播组 https stackoverflow com questions 6616922 how to create socket io multicast groups 6624604 6624
  • Jquery 子元素发生变化

    我正在尝试使用 jquery 在子元素 在本例中为 select 更改时触发事件 这是我的 HTML div class row addForm div class col lg 2 col md 2 col sm 3 col xs 6 d
  • 如何停止 PythonShell

    如何终止 停止 Node js 中 PythonShell 执行的 Python 脚本的执行 我在交互模式下运行 输出通过 socket io 发送到给定的房间 如果没有更多的客户端连接到这个房间 我想停止 python 脚本的执行 这是我
  • 带有桌子的嵌套表

    我在应用了表排序器的表中嵌套了表 它在嵌套表中添加了排序标题 但是它们没有对行进行排序 并且抛出了JavaScript错误 我想拥有 嵌套表不可排序 巢表上的排序实际上可以工作 但不是现状 您的第一个选择要容易得多 使嵌套表不可排序 像这样
  • Intern JS - 如何在链式 Command 方法中使用 Promise.all()?

    我是用 Intern JS 编写测试的新手 并且一直在遵循他们的文档来使用对象接口 https theintern github io intern interface object and 页面对象 https theintern git
  • Kendo 刷新 (DropDownList.refresh()) 不起作用错误未定义

    我试图在另一个 DropDownList 更改后刷新下拉列表 但 Refresh 方法未定义错误正在升级 我尝试再次读取数据源 它显示它正在加载 但数据仍然相同 帮助解决这个问题请 Code DropDownList1 change fun
  • redux - 如何存储和更新键/值对

    我正在使用 redux 和 React js 我想存储简单的键 值对 但无法获得正确的减速器语法 在这种情况下 每个键 值对将保持与外部系统的连接 这是正确的做法吗 我刚开始使用 redux 所以这有点神秘 export default s
  • 除非打开开发人员工具,否则 IE8 Javascript 无法运行?

    由于某种原因 在 IE8 中 除非我在打开开发工具的情况下重新加载页面 否则 javascript 不会运行 我关闭开发人员工具并重新加载页面 然后 javascript 停止工作 我没有收到任何错误报告 无论如何它们也没有任何用处 还有其
  • 如何在react.js中将/n替换为换行符?

    我正在尝试更换每一个 n to a br tag in ReactJS In my note note对象有一个包含多个的字符串 n in it 示例注释 注释 test ntest ntest 我尝试过的ReactJS note note
  • Node.js 上的 Connect 出现“无法 GET /”

    我正在尝试使用以下方式开始提供一些静态网页connect像这样 var connect require connect var nowjs require now var io require socket io var app conne

随机推荐

  • C# 中的对象指针(object*)

    我想要做的是 我想传递一个指向函数的指针 该函数可以是任何类型的变量 int long string 甚至是一个类 我的意思是我应该能够传递任何变量的指针 我就是这样做的 unsafe class whatever whatever obj
  • 声明原子指针与原子指针

    据我所知 以下声明创建了一个值数组 每个值都是原子的 Atomic int x 10 但是 我不清楚这是否 Atomic int x x calloc 10 sizeof int 创建一个包含 10 个原子整数的数组 或者是指向非原子整数数
  • 计算文本的正确宽度

    我需要阅读由 AutoCAD 导出为 PDF 的计划 并使用 PDFBox 在其上放置一些带有文本的标记 除了计算写在标记旁边的文本宽度之外 一切正常 我浏览了整个 PDF 规范并详细阅读了涉及图形和文本的部分 但无济于事 据我了解 字形坐
  • Mac OS 10.16 链接 Homebrew 安装的库

    我已经使用自制程序很长时间了 从未遇到过这个奇怪的问题 由于某种原因 我不会在这里解释我使用的是 MacOS 10 16 Big Sur 这是最新 MacOS 的 Beta 版本 并且已经使用自制软件安装了库 其中一个图书馆是zlib 但是
  • XPath max 函数和括号的使用

    假设我们有以下 XML
  • 无法找出注册表中的 ActiveRecord::SubclassNotFound#edit?

    当处于 编辑 或 显示 状态时 会出现以下情况 ActiveRecord SubclassNotFound 在注册表中 edit 单表继承机制无法定位子类 Plane 出现此错误是因为列 type 被保留用于在继承时存储类 如果您不希望这样
  • 为什么他们在 Mongoose Population 示例中使用 ObjectId 和 Number?

    In this例如 他们创建personSchema using ObjectId来参考Story我明白这一点 但随后在storySchema他们为什么不做同样的事情来引用这个人呢 或者反过来 为什么在 Person 中使用 ObjectI
  • 获取表的列名并将它们存储在字符串或var中c#asp.net

    我想知道如何获取数据库表的列并将它们存储在字符串或字符串数 组中 我有以下代码 但我相信它不起作用 我正在使用 asp net 中给出的默认表 我已经能够毫无问题地写入该表 但我不知道如何从中选择并保存检索到的值 这是我后面的代码中的内容
  • 传递类方法而不是 std::sort 中的函数

    在一个类中 我试图通过传递同一类的方法来对向量进行排序 但是编译的时候会报错 谁能告诉我问题是什么吗 谢谢你 它给出以下错误 类型参数bool Sorter D D does not match书 排序器 D D c 我也尝试过使用sort
  • tao SimpleOpenGlControl 错误

    我正在创建一个包含 Tao Platform Windows SimpleOpenGlControl 的用户控件 在我的控件的构造函数中 我有 InitializeComponent simpleOpenGlControl1 Initial
  • 将 javascript 变量发送到经典 asp

    我有一个基于 jQuery 的成本计算器 我希望网页能够通过电子邮件发送计算 器值的摘要 服务器在经典 ASP 上运行 如何使用 ASP 检索 javascript 变量 据我了解 ASP 代码在页面加载之前运行 而 javascript
  • Python Opencv 和 Sockets - 以 h264 编码的流视频

    所以我正在尝试制作一个流媒体 将视频从局域网上的一台计算机流式传输到另一台计算机 或目前同一台计算机 我需要它使用尽可能少的带宽 所以我尝试用 h264 进行编码 我在做这件事时遇到了困难 我真的不知道从哪里开始 现在它是用jpg编码的 并
  • 计算某个项目在多列中每一列中出现的次数

    我想读取一个表并创建另一个表来计算唯一 ID 在多个特定列中出现的次数 例如 我有一个表 其中每一行显示一个事务 并用一个 userId 标识每个人的角色 buyer lt c A A B A B C seller lt c C B C B
  • 不使用 #define 定义 BIT0、BIT1、BIT2 等

    在C 中是否可以在不使用 define的情况下以另一种方式定义BIT0 BIT1 BIT2 define BIT0 0x00000001 define BIT1 0x00000002 define BIT2 0x00000004 然后我采用
  • 使用 python 编辑 tfvars 文件

    我不知道我问的是否是正确的组 但是有没有办法使用 python 编辑 tfvars 例如 我有一个 tfvars 文件 其中一些变量具有以下值 owner operations port number 80 我想编辑port number
  • Apache Shiro JdbcRealm 与 JavaConfig 和 Spring Boot

    我正在尝试配置我的 Spring Boot 应用程序以使用 Apache Shiro 作为其安全框架 我已经完成了与 PropertiesRealm 一起使用的所有操作 现在我正在尝试使其与 JdbcRealm 和 Spring Boot
  • 是否可以在android上通过textview显示纯html代码

    我正在尝试在我的 Android 应用程序上使用 TextView 显示 HTML 字符串 我很好奇如何才能通过 TextView 显示内联样式的 HTML 由于某些原因 我们不能使用 WebView 来实现此目的 GitHub 上是否有您
  • 错误:无法确定 --prod 中类 OverlayPortal 的模块

    我不确定我只面临一个问题ionic cordova run android prod and my ionic cordova run android工作正常 ERROR Error Cannot determine the module
  • 将表达式计算为字符串,返回对象?

    基本上我有一些代码 当它发生时 我需要将某个对象设置为等于某个表达式 所有这些 做什么 爵士乐都存储为字符串 所以我解析它 并使用反射来查找我正在执行此操作的对象 现在我需要找出如何将值存储到该对象 问题是该值可能是 1 1 5 2 或 某
  • 如何使用 Puppeteer 计算页面完全加载时间?

    我试图使用 Node 中的 puppeteer 在几秒钟内获得页面完全加载时间 为此我对 API 和其他问题进行了一些研究 并创建了以下代码 First Configuration puppeteer launch defaultViewp