playwright 頁面載入速度度量(錯誤之處,敬請斧正)

难以怀瑾發表於2024-03-25

參考文件:
如何有效度量前端效能 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()

相關文章