搭建自動化 Web 頁面性能檢測系統 —— 設計篇
我們是袋鼠云數棧 UED 團隊,致力于打造優秀的一站式數據中臺產品。我們始終保持工匠精神,探索前端道路,為社區積累并傳播經驗價值。。
本文作者:琉易 liuxianyu.cn
頁面性能對于用戶體驗、用戶留存有著重要影響,當頁面加載時間過長時,往往會伴隨著一部分用戶的流失,也會帶來一些用戶差評。性能的優劣往往是同類產品中勝出的影響因素,也是一個網站口碑的重要評判標準。
一、名稱解釋
前端監控一般分為合成監控和真實用戶監控。
1.1、合成監控
合成監控就是模擬用戶的使用場景,訪問一個頁面,通過一些工具和規則去檢測頁面,提取一些性能指標,生成一份檢測報告,注重檢測。
合成監控的優缺點:
優點 | 缺點 |
---|---|
實現簡單,社區方案成熟 | 配置復雜,不能完全還原用戶真實場景 |
能采集到更豐富的數據 | 登錄等場景需要單獨處理 |
不影響真實用戶的頁面訪問性能 | 單次檢測數據不夠準確 |
1.2、真實用戶監控
真實用戶監控是指用戶在頁面上訪問,訪問時會產生各類性能數據,在用戶訪問停止的時候,將這些性能數據傳輸到服務端,進行數據整理分析的過程,注重監控。
真實用戶監控的優缺點:
優點 | 缺點 |
---|---|
完全還原用戶真實場景 | 對用戶的訪問性能有一定影響 |
登錄等場景無需單獨解決 | 無法采集完整的資源加載瀑布圖 |
數據樣本足夠大且真實,數據價值高 | 無法可視化展示頁面加載過程 |
1.3、定義合適的性能指標
- 首次內容渲染時長(First Contentful Paint, FCP)
頁面最新出現的內容渲染時長 - 首次展現平均值(Speed Index, SI)
頁面內容可見填充的速度 - 最大內容繪制時間(Largest Contentful Paint, LCP)
頁面核心內容呈現時間,不采用 loading 狀態的數據 - 可交互時間(Time to Interactive, TTI)
用戶是否會體驗到卡頓 - 總阻塞時間(Total Blocking Time, TBT)
主線程被阻塞的時間,無法作出輸入響應 - 累計布局樣式偏移(Cumulative Layout Shift, CLS)
二、為什么做
基于需要對公司的 Web 產品進行性能優化,在做性能優化的同時,優化的衡量標準也不可或缺。在頁面開發時觀察頁面的性能并不夠準確,因為不同的開發設備性能表現不同,所伴隨的變量也較多,不能夠準確的反映性能優化效果,也無法觀察產品的性能變化趨勢。為什么自研呢,自研有以下好處:
(1)借助第三方的性能檢測服務往往不能保證檢測數據的安全性。
(2)第三方的性能檢測服務一般無法與公司內部系統打通流程,一般無法自動化檢測公司內部產品。
(3)可以做一些自定義開發,比如根據產品特點調整不同的性能指標權重,從而更準確的計算分數。
那么在檢測收集到了這么多的指標數據后,頁面性能到底如何呢,如果你的老板問你公司的產品頁面性能如何,你該如何回復呢?假設列舉一大堆時間指標、偏移量等數據,老板看到這些數值的時候可能就是一頭霧水,根本理解不了產品的頁面性能到底如何。那么自研可以針對產品類型,給出一個統一的標準,這樣就方便去對比各個產品的性能表現了。
三、怎么做
3.1、基礎依賴
下面是檢測系統的整體架構:
這里設計的性能檢測系統主要包含前端頁面和服務端,其中:
前端頁面展示性能檢測入口、檢測結果、性能趨勢、性能排行榜等。
服務端基于 Nestjs + Lighthouse + Puppeteer 實現,通過 Typeorm 操作 MySQL 數據庫,記錄和查詢性能檢測數據。
另外輔助一些插件進行定時監測、結果通知等操作,實現自動化檢測,相比頁面開發時通過開發者工具中的 Lighthouse 檢測有以下好處:
(1)不用開發者主動觸發;
(2)不會阻塞開發過程,無需等待;
Lighthouse 用于檢測 Web 網頁的性能,主要基于 4 個主要步驟實現,分別是交互驅動、性能數據收集、審計整理以及記錄。具體為:
(1)用戶在性能檢測入口輸入待檢測的頁面地址,點擊開始檢測,頁面通過接口調用性能檢測服務
(2)Lighthouse 遍歷當前頁面的收集器方法并合成一個總的收集器方法以便于采集數據
(3)對上述采集到的性能數據進行計算和評分
Lighthouse 主要提供六個收集器,通過以下六個收集器即可采集到和實際訪問接近的性能數據,每個收集器的功能不一,如下:
(1)收集 DOM 元素相關數據、DOM 節點最大深度、滾動條等
(2)收集頁面內的所有圖片資源,并記錄下每個圖片元素的寬高和定位等屬性
(3)收集相關指標,如:FCP、LCP、CLS 等
(4)收集 JS 事件監聽數量、JS 堆棧等
(5)收集頁面的所有請求,包括狀態碼、請求頭、響應頭、請求方式等
(6)收集 window.performance 下的性能數據,用于計算加載時間
Puppeteer 是 Chrome 團隊提供的一個無界面 Chrome 工具,俗稱無頭瀏覽器,通過提供的 API 可以控制 Node 端的 Chrome 工具進行指定的操作。在這里設計的性能檢測系統中,由于 Lighthouse 進行檢測時打開的類似于無痕窗口,沒有登錄信息,所以 Puppeteer 主要幫助我們實現模擬登錄。
當檢測頁面需要登錄時,分析出頁面屬于哪個 devops 實例,然后通過 Puppeteer 跳轉到對應的登錄頁面,然后輸入用戶名、密碼、驗證碼,待登錄完成后跳轉至正確的頁面,再進行頁面性能檢測。如果登錄后還在登錄頁,表示登錄失敗,則獲取錯誤提示并拋出。
以下是檢測系統的一個流程圖:
3.2、關鍵代碼
// 開始檢測
async run(urlDto: UrlDto): Promise<object> {
const start = new Date().getTime();
try {
const { url, loginUrl } = urlDto;
const needLogin = url.includes('devops') || loginUrl;
console.log(`本次檢測${needLogin ? '' : '不'}需要登錄`, url);
const runResult = needLogin
? await this.withLogin(urlDto)
: await this.withOutLogin(url);
// 保存檢測結果文件,便于預覽
const urlStr = url.replace(/http(s?):\/\//g, '').replace(/\//g, '');
fs.writeFileSync(`./static/${urlStr}-report.html`, runResult?.report);
// 性能數據
const performance = runResult?.lhr?.categories?.performance || {};
const data = {
...performance,
auditRefs: performance?.auditRefs?.filter((item) => item.weight),
};
// console.log(data);
console.log(`本次耗時:${((new Date().getTime() - start) / 1000).toFixed(2)}s`);
return {
code: 200,
data,
message: `耗時:${((new Date().getTime() - start) / 1000).toFixed(2)}s`,
};
} catch (error) {
return {
code: 401,
message: error,
};
}
}
3.3、檢測規則
系統除了支持手動輸入網頁地址檢測,也支持自動檢測。為了便于統計每個子產品的真實表現,每天凌晨自動檢測 10 次,去掉最高分,去掉最低分,從其余分數中選擇中位數作為每天的檢測評分。
性能檢測時的數據采集可能因為網頁服務的不穩定性,導致有偏大或偏小的數據,所以提供某個時間段某個指標的直方圖來分析數據的基本特征。也會提供某個產品的整體分數趨勢,便于統計某個時間段內該產品的性能變化,也可以提現性能優化前后的效果。
四、寫在后面
這篇文章簡單介紹了下該性能檢測系統的初步設計、一些頁面性能的概念以及采用的技術點,后續請關注《搭建自動化 Web 頁面性能檢測系統 —— 實踐篇》。
最后
歡迎關注【袋鼠云數棧UED團隊】~
袋鼠云數棧UED團隊持續為廣大開發者分享技術成果,相繼參與開源了歡迎star