Node.js使用Playwright自动化测试页面性能

 更新时间:2024年11月20日 11:24:26   作者:前端安迪  
对于现在的网站而言,性能的重要性不言而喻,本文将使用Playwright自动化测试页面性能,感兴趣的小伙伴可以跟随小编一起学习一下

概要

对于现在的网站而言,性能的重要性不言而喻,每一家公司的网站都在追求更快地性能,更好地体验,但是,该怎么去找到影响网站速度的因素,如何优化性能,这是一个非常考验前端工程师技术功底的时刻。

但其实,现代浏览器公开了许多的性能指标,这些指标可以帮我们快速确定需要改进的内容和改进方法,今天,我想和大家介绍一种方案,使用Playwright自动化测试页面性能。

对 Playwright 不了解的同学,可以移步我的上一篇文章了解: Playwright使用指南

我们可以通过 Playwright 查询浏览器提供的各种与性能相关的 API,然后识别导致网站速度变慢的原因。比如,Chrome 浏览器提供了WebVitals 指标,这些指标包括Time to First Byte (TTFB)Total BlockTime (TBT) First Contentful Paint (FCP),这是非常好的衡量用户体验的指标,很值得我们在测试中进行监控。

接下来,给大家介绍几种常见的衡量页面性能的方案。

导航和资源加载时间 API

这个API允许你检索和页面加载时间相关的所有事件的时间,比如domComplete time , duration 和 connectEnd。我们可以在测试过程中使用这些指标来检测网页性能情况。

1. Performance 得分

我们可以使用Playwright定期检查页面性能,确保网页的性能不低于你设置的某个特定标准。

例如下面的这段代码,我们可以使用 Playwright 来自动化检测淘宝网的 domComplete 时间,如果它低于某一个阈值,然后会提醒我们测试用例失败,这样我们就可以及时去对页面做性能回归。

import { chromium } from 'playwright';

(async () => {
  const browser = await chromium.launch({
    headless: true,
  });
  const context = await browser.newContext()
  const page = await context.newPage()

  await page.goto('https://www.taobao.com/');
  
  const navigationTimingJson = await page.evaluate(() =>
    JSON.stringify(performance.getEntriesByType('navigation'))
  )
  const navigationTiming = JSON.parse(navigationTimingJson)

  if (navigationTiming.domComplete < 2000) {
    console.error('ERROR: domComplete below 2 seconds')
  }

  await browser.close()
})()

2. 资源加载时间 API

这个API 提供了一种可以让我们获取页面特定资源加载时间的方法,方便我们衡量页面资源加载时间。

例如,我们可以使用下面这段代码来检查淘宝网首页的webp格式图片的加载时间。

import { chromium } from 'playwright';

(async () => {
  const browser = await chromium.launch({
    headless: true,
  });
  const context = await browser.newContext()
  const page = await context.newPage()

  await page.goto('https://www.taobao.com/');
  
  const resourceTimingJson = await page.evaluate(() =>
    JSON.stringify(window.performance.getEntriesByType('resource'))
  )

  const resourceTiming = JSON.parse(resourceTimingJson)
  const logoResourceTiming = resourceTiming.find((element) =>
    element.name.includes('.webp')
  )

  console.log(logoResourceTiming)

  await browser.close()
})()

页面绘制时间 API

我们可以使用页面绘制时间 API 来检索页面 First Paint (FP)First Contentful Paint (FCP)的时间。

import { chromium } from 'playwright';

(async () => {
  const browser = await chromium.launch({
    headless: true,
  });

  const context = await browser.newContext()
  const page = await context.newPage()

  await page.goto('https://www.taobao.com/');
  
  const paintTimingJson = await page.evaluate(() =>
    JSON.stringify(window.performance.getEntriesByType('paint'))
  )
  const paintTiming = JSON.parse(paintTimingJson)

  console.log(paintTiming)

  await browser.close()

})()

布局稳定性 API

这个API可以提供有关页面布局变化的信息,可以用来计算网页的 Core Web Vital Cumulative Layout Shift (CLS) 数据

import { chromium } from 'playwright';

(async () => {
  const browser = await chromium.launch({
    headless: true,
  });

  const context = await browser.newContext()
  const page = await context.newPage()

  await page.goto('https://www.taobao.com/');
  
  const cummulativeLayoutShift = await page.evaluate(() => {
    return new Promise((resolve) => {
      let CLS = 0

      new PerformanceObserver((l) => {
        const entries = l.getEntries()

        entries.forEach(entry => {
          if (!entry.hadRecentInput) {
            CLS += entry.value
          }
        })

        resolve(CLS)
      }).observe({
        type: 'layout-shift',
        buffered: true
      })
    })
  })

  console.log(parseFloat(cummulativeLayoutShift))

  await browser.close()

})()

Long Task(长任务) API

Long Task API 会返回一个Javascript 执行列表,这些列表中的执行需要50毫秒才能完成,意味着阻塞了页面的UI线程,造成页面卡顿。我们可以用这个API来计算页面的总阻塞时间 Total Blocking Time (TBT).

例如下面这段代码,我们使用了 PerformanceObserver 来计算出页面长任务时间超过50毫秒的时间之和。

import { chromium } from 'playwright';

(async () => {
  const browser = await chromium.launch({
    headless: true,
  });

  const context = await browser.newContext()
  const page = await context.newPage()

  await page.goto('https://www.taobao.com/');
  

  const totalBlockingTime = await page.evaluate(() => {
    return new Promise((resolve) => {
      let totalBlockingTime = 0
      new PerformanceObserver(function (list) {
        const perfEntries = list.getEntries()
        for (const perfEntry of perfEntries) {
          totalBlockingTime += perfEntry.duration - 50
        }
        resolve(totalBlockingTime)
      }).observe({ type: 'longtask', buffered: true })

      // Resolve promise if there haven't been any long tasks
      setTimeout(() => resolve(totalBlockingTime), 5000)
    })
  })

  console.log(parseFloat(totalBlockingTime))

  await browser.close()

})()

Chrome DevTools Performance

Chrome DevTools 提供了很多非常有用的功能,我们可以充分利用起来。例如,我们可以使用Network.emulateNetworkConditions 来控制浏览器网速。

import { chromium } from 'playwright';

(async () => {
  const browser = await chromium.launch({
    headless: true,
  });

  const context = await browser.newContext()
  const page = await context.newPage()

  await page.goto('https://www.taobao.com/');
  
  const context = await browser.newContext()
  const page = await context.newPage()

  await client.send('Network.enable')
  await client.send('Network.emulateNetworkConditions', {
    offline: false,
    downloadThroughput: (5 * 1024 * 1024) / 8,
    uploadThroughput: (4 * 1024 * 1024) / 8,
    latency: 30
  )

  await page.goto('https://testingbot.com/');
  await browser.close()


})()

以上就是Node.js使用Playwright自动化测试页面性能的详细内容,更多关于Playwright测试页面性能的资料请关注脚本之家其它相关文章!

相关文章

  • nodeJs编写错误处理中间件问题

    nodeJs编写错误处理中间件问题

    这篇文章主要介绍了nodeJs编写错误处理中间件问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • NodeJs 文件系统操作模块fs使用方法详解

    NodeJs 文件系统操作模块fs使用方法详解

    这篇文章主要介绍了NodeJs 文件系统操作模块fs使用方法,需要的朋友可以参考下
    2018-11-11
  • 关于Node.js中的JXcore打包示例

    关于Node.js中的JXcore打包示例

    这篇文章主要介绍了关于Node.js中的JXcore打包示例,JXcore 是一个支持多线程的 Node.js 发行版本,基本不需要对你现有的代码做任何改动就可以直接线程安全地以多线程运行,需要的朋友可以参考下
    2023-05-05
  • node.js中的fs.readSync方法使用说明

    node.js中的fs.readSync方法使用说明

    这篇文章主要介绍了node.js中的fs.readSync方法使用说明,本文介绍了fs.readSync方法说明、语法、接收参数、使用实例和实现源码,需要的朋友可以参考下
    2014-12-12
  • node.js中module.exports与exports用法上的区别

    node.js中module.exports与exports用法上的区别

    Node.js 引入了模块(Module)概念,一个模块可以通过module.exports 或 exports 将函数、变量等导出,以使其它 JavaScript 脚本通过require() 函数引入并使用。那么node.js中module.exports与exports有什么区别呢?下面小编给大家解答下
    2016-09-09
  • nodejs子进程child_process和cluster模块深入解析

    nodejs子进程child_process和cluster模块深入解析

    本文从node的单线程单进程的理解触发,介绍了child_process模块和cluster模块,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • node.js判断连接池是否正确连接上的两种方法

    node.js判断连接池是否正确连接上的两种方法

    在使用mysql2/promise的createPool时,连接是懒加载的,只有在执行查询或手动获取连接时才会尝试建立,推荐手动获取并释放一个连接或执行一个简单的测试查询来判断连接是否正确,本文给大家介绍node.js判断连接池是否正确连接上的两种方法,感兴趣的朋友跟随小编一起看看吧
    2026-01-01
  • 从零开始学习Node.js系列教程之设置HTTP头的方法示例

    从零开始学习Node.js系列教程之设置HTTP头的方法示例

    这篇文章主要介绍了Node.js设置HTTP头的方法,详细分析了常见HTTP头的功能、原理及相关设置操作技巧,需要的朋友可以参考下
    2017-04-04
  • node.js中的console.timeEnd方法使用说明

    node.js中的console.timeEnd方法使用说明

    这篇文章主要介绍了node.js中的console.timeEnd方法使用说明,本文介绍了console.timeEnd的方法说明、语法、使用实例和实现源码,需要的朋友可以参考下
    2014-12-12
  • nodejs简单实现操作arduino

    nodejs简单实现操作arduino

    本文给大家分享的是使用nodejs来驱动arduino,主要是基于cylonjs 和 gort,有需要的小伙伴可以参考下
    2016-09-09

最新评论