性能常识 playwright 页面加载速度度量(错误之处,敬请斧正)

难以怀瑾 · 2024年03月25日 · 4923 次阅读

参考文档:
如何有效度量前端性能 https://testerhome.com/topics/35529
前端性能监控:window.performance https://www.cnblogs.com/libin-1/p/6501951.html

1 前言:三种加载方式

  1. 正常重加载(Normal Reload) 快捷键:F5 或 Ctrl + R 总结:根据缓存控制头判断缓存是否过期 > 正常重加载是通过点击浏览器地址栏旁边的刷新按钮或者使用快捷键(通常是 F5)来触发的。 在正常重加载中,浏览器会检查页面中的缓存控制头(例如 Cache-Control、Expires 等),并根据这些头信息来决定是否使用缓存。如果服务器响应中包含了不需要缓存的标志,或者缓存时间已经过期,浏览器就会强制重新请求页面的内容,否则就会使用缓存。 > 正常重加载只会重新请求那些被修改了或者过期的资源,对于未修改且仍在缓存有效期内的资源,浏览器会直接从缓存中加载。

2 硬性重加载(Hard Reload):
快捷键:Shift + F5 Ctrl + Shift + R 或 Ctrl + F5
总结:缓存中有未过期的资源,浏览器也会忽略它们,强制从服务器重新获取

硬性重加载是通过按住 Shift 键同时点击刷新按钮(或者使用快捷键 Shift + F5)来触发的。
硬性重加载会忽略浏览器缓存,并强制重新请求页面的所有资源,包括 HTML、CSS、JavaScript
等。即使缓存中有未过期的资源,浏览器也会忽略它们,强制从服务器重新获取。

3 清空缓存并硬性重加载(Empty Cache and Hard Reload):
快捷键:无
总结: 彻底清除浏览器中的所有缓存,强制从服务器重新获取,(与 硬性重加载 胜在彻底二字吧?具体场景未知)

这种方式会先清空浏览器的缓存,然后再进行硬性重加载。它会彻底清除浏览器中的所有缓存,包括缓存的页面、图片、脚本等,然后再强制重新请求页面的所有资源。

2 如何度量

  • 主要是使用 js 里 window.performance 相关数据进行度量
  • 主要参数 通过白屏时间、首屏时间和加载总时间进行度量

  • 白屏时间(Blank Screen Time):白屏时间是指从页面开始加载到浏览器首次绘制内容之间的时间间隔。它表示了用户在访问页面时看到空白屏幕的持续时间。计算白屏时间的一种方法是通过 Performance API 中的 domLoading 和 domInteractive 时间戳来计算,即 domInteractive - navigationStart。

  • 首屏时间(First Screen Time)或(FCP First Contentful Panit 首次内容绘制):首屏时间是指页面上首次有内容绘制出来的时间。它反映了用户在页面加载过程中首次看到有意义内容的时间点。计算首屏时间的一种方法是通过 Performance API 中的 domContentLoadedEventStart 时间戳来计算,即 domContentLoadedEventStart - navigationStart。

  • 加载总时间 页面上所有资源(包括文档、图片、脚本、样式表等)加载完成的时间点与请求 url 之间的耗时
    loadEventEnd - navigationStart

  • window.performance.timing 相关参数介绍

  • navigationStart 代表浏览器开始 unload 前一个页面文档的开始时间节点。比如我们当前正在浏览 baidu.com,在地址栏输入 google.com 并回车,浏览器的执行动作依次为:unload 当前文档(即 baidu.com)->请求下一文档(即 google.com)。-

  • loadEventEnd 表示了页面上所有资源(包括文档、图片、脚本、样式表等)加载完成的时间点

  • domInteractive 代表浏览器解析 html 文档的状态为 interactive 时的时间节点。domInteractive 并非 DOMReady,它早于 DOMReady 触发,代表 html 文档解析完毕(即 dom tree 创建完成)但是内嵌资源(比如外链 css、js 等)还未加载的时间点;

  • domContentLoadedEventStart:代表 DOMContentLoaded 事件触发的时间节点:
    页面文档完全加载并解析完毕之后,会触发 DOMContentLoaded 事件,HTML 文档不会等待样式文件,图片文件,子框架页面的加载 (load 事件可以用来检测 HTML 页面是否完全加载完毕 (fully-loaded))

    3 每个文件的加载时间

  • 获取每个资源的名称、耗时、大小、协议

    const resource= window.performance.getEntriesByType('resource') 
    //获得某一些数据
    

const resources = resource.map(entry => {
return {
name: entry.name,
duration:(entry.duration/1000).toFixed(3),//时间转为秒 保留三位小数
size: (entry.transferSize/1024/1024).toFixed(3), // 大小转为 MB,保留三位小数
protocol: entry.nextHopProtocol
};
});


- 注意的点:window.performance.timing记录当前页面的性能指标
> window.performance.timing 记录的性能指标是针对当前文档的加载和渲染过程的。在浏览器中,每个页面都有自己的
> window.performance.timing 对象,它记录了与该页面加载和渲染过程相关的时间点和持续时间。因此,当你访问
> window.performance.timing 时,它提供的数据是当前页面的性能指标。
> 
> 代码如下
```python
import json
from playwright.sync_api import sync_playwright
def login_load_login_time():
    with sync_playwright() as playwright:
        # print(playwright.chromium.executable_path)
        browser = playwright.chromium.launch(headless=True)
        # 设置测试网站的URL
        url = "http://xxx.xxx.xxx.xxx:xxxx/"
        # js代码
        performance_js = '''() => {
                    // 使用 window.performance.timing 获取性能指标
                    const timing = window.performance.timing;
                    const resource= window.performance.getEntriesByType('resource') 
                    //获得某一些数据

                    const resources = resource.map(entry => {
                        return {
                            name: entry.name,
                            duration:(entry.duration/1000).toFixed(3),//时间转为秒 保留三位小数
                            size: (entry.transferSize/1024/1024).toFixed(3), // 大小转为MB,保留三位小数
                            protocol: entry.nextHopProtocol
                        };
                    });

                    // 计算页面加载时间 
                    //navigationStart 代表浏览器开始unload前一个页面文档的开始时间节点。比如我们当前正在浏览baidu.com,在地址栏输入google.com并回车,浏览器的执行动作依次为:unload当前文档(即baidu.com)->请求下一文档(即google.com)。navigationStart的值便是触发unload当前文档的时间节点。
                    // loadEventEnd 表示了页面上所有资源(包括文档、图片、脚本、样式表等)加载完成的时间点
                    const loadTime = timing.loadEventEnd - timing.navigationStart;
                    // 计算白屏时间
                    const blankScreenTime = timing.domInteractive - timing.navigationStart;

                    // 计算首屏时间
                    const firstScreenTime = timing.domContentLoadedEventStart - timing.navigationStart;

                    // 获取 LCP 时间
                    const lcpEntries = window.performance.getEntriesByType('largest-contentful-paint');
                    const lcpTime = lcpEntries.length > 0 ? lcpEntries[0].startTime : null;

                    // 构造一个性能指标对象
                    // 提取资源名称和大小


                    return {
                        "loadTime": (loadTime/1000).toFixed(3),
                        "blankScreenTime": (blankScreenTime).toFixed(3),
                        "firstScreenTime": (firstScreenTime).toFixed(3),
                        "lcpTime":lcpTime,
                        "resource":resources
                    };
                }'''
        # 在浏览器中打开网页
        page = browser.new_page()
        page.set_viewport_size({"width": 1920, "height": 1080})
        # 先打开一个弹窗 监听load事件
        page.goto(url, wait_until='load')
        first_performance = page.evaluate(performance_js)

        # 进行普通刷新
        page.reload(wait_until='load')

        reload_performance = page.evaluate(performance_js)

        print(first_performance)
        print(reload_performance)
        with open(file=r"./login.txt", mode="a", encoding="utf8") as f:
            f.write(json.dumps(first_performance))
            f.write("\n")
            f.write(json.dumps(reload_performance))
            f.write("\n")


if __name__ == '__main__':
    login_load_login_time()

共收到 0 条回复 时间 点赞
难以怀瑾 关于页面加载耗时测试 中提及了此贴 05月10日 18:17
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册