>我們是[袋鼠雲數棧 UED 團隊](http://ued.dtstack.cn/),致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。。 >本文作者:琉易 [liuxianyu.cn](https://link.juejin.cn/?target=h ...
我們是袋鼠雲數棧 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
- 大數據分散式任務調度系統——Taier
- 輕量級的 Web IDE UI 框架——Molecule
- 針對大數據領域的 SQL Parser 項目——dt-sql-parser
- 袋鼠雲數棧前端團隊代碼評審工程實踐文檔——code-review-practices
- 一個速度更快、配置更靈活、使用更簡單的模塊打包器——ko