補齊Web前端性能分析的工具盲點
最近依然在研究大型專案,而大型專案最容易遇到的問題便是性能問題。 一般來說,當我們遇到性能瓶頸的時候,才會開始去進行相應的分析。 分析的方向除了業務本身的特點相關之外,常見的我們還可以藉助一些工具來發現問題。 本文一起來研究下,前端性能分析可以怎麼走~
# 前端性能分析工具(Chrome DevTools)
一般來說,前端的性能分析通常可以從時間和空間兩個角度來進行:
- 時間:常見耗時,如頁面載入耗時、渲染耗時、網路耗時、腳本執行耗時等
- 空間:資源佔用,包括CPU佔用、記憶體佔用、本地緩存佔用等
那麼,下面來看看有哪些常見的工具可以借來用用。 由於我們的網頁基本上跑在瀏覽器中,所以基本上大多數的工具都來源於瀏覽器自身提供,首當其衝的當然是 Chrome DevTools。 本文我們也主要圍繞 Chrome DevTools 來進行說明。
## Lighthouse
Lighthouse 的前身是 Chrome DevTools 面板中的 Audits。 在 Chrome 60 之前的版本中, 這個面板只包含網路使用率和頁面性能兩個測量類別,從 Chrome 60 版本開始, Audits 面板已經被 Lighthouse 的整合版取代。 而在最新版本的 Chrome 中,則需要單獨安裝 Lighthouse 拓展程式來使用,也可以通過腳本來使用。
### 架構

下面是 Lighthouse 的組成部分:
- 驅動(Driver):和 Chrome Debugging Protocol 進行互動的介面
- 收集器(Gatherers):使用驅動程式收集頁面的訊息,收集器的輸出結果被稱為 Artifact
- 審查器(Audits):將 Artifact 作為輸入,審查器會對其運行測試,然後分配通過/失敗/得分的結果
- 報告(Report):將審查的結果分組到面向用戶的報告中(如最佳實踐),對該部分應用加權和總體然後得出評分
### 主要功能
Lighthouse 會在一系列的測試下運行網頁,比如不同尺寸的設備和不同的網路速度。 它還會檢查頁面對輔助功能指南的一致性,例如顏色對比度和ARIA最佳實踐。
在比較短的時間內,Lighthouse 可以給出這樣一份報告(可將報告生成為 JSON 或 HTML):

這份報告從 5 個方面來分析頁面: 效能、輔助功能、最佳實務、搜尋引擎最佳化和 PWA。 像性能方面,會給出一些常見的耗時統計。 除此以外,還會給到一些詳細的優化方向。
如果你希望短時間內對你的網站進行較全面的評估,可以使用 Lighthouse 來跑一下分數,確定大致的優化方向。
## Performance 面板
Performance 面板同樣有個前身,叫 Timeline。 該面板用於記錄和分析運行時性能,運行時性能是頁面運行時(而不是載入)的性能。
### 使用步驟
Performance 面板功能特別多,具體的分析也可以單獨講一篇了。 這裡我們簡單說一下使用的步驟:
- 在隱身模式下打開 Chrome。 隱身模式可確保 Chrome 以乾淨狀態運行,例如瀏覽器的擴展可能會在性能評估中產生影響。
- 在 DevTools 中,按兩下「Performance」選項卡,並進行一些基礎配置(更多參考官方說明)。
- 按照提示按下記錄,開始記錄。 進行完相應的操作之後,點擊停止。
- 當頁面運行時,DevTools 捕獲性能指標。 停止記錄后,DevTools 處理數據,然後在 Performance 面板上顯示結果。
### 主要功能
關於 Performance 怎麼使用的文章特別多,大家網上隨便搜一下就能搜到。 一般來說,主要使用以下功能:

- 查看 FPS 圖表:當在 FPS 上方看到紅色條形時,表示幀速率下降得太低,以至於可能損害用戶體驗。 通常,綠色條越高,FPS 越高
- 查看 CPU 圖表:CPU 圖表在 FPS 圖表下方。 CPU 圖表的顏色對應於性能板的底部的 Summary 選項卡
- 查看 火焰圖:火焰圖直觀地表示出了內部的CPU分析,橫軸是時間,縱軸是調用指標,調用棧最頂端的函數在最下方。 啟用 JS 分析器後,火焰圖會顯示數據的每個 JavaScript 函數,可用於分析具體函數
- 查看 Buttom-up:此檢視可以看到某些函數對性能影響最大,並能夠檢查這些函數的調用路徑
具體要怎麼定位某些性能瓶頸,可以參考官方文檔系列文章,這裡就不詳細介紹啦。
## Performance Monitor
打開 Chrome 控制台後,按組合鍵 ctrl + p
(Mac 快速鍵為 command + p
),輸入 > Show Performance Monitor
,就可以打開 Performance Monitor 性能監視器。 主要的監控指標包括:
- CPU usage:CPU 佔用率
- JS head size:JS 記憶體使用大小
- DOM Nodes:記憶體中掛載的 DOM 節點個數
- JS event listeners:事件監聽數
- ... :其他等等
大多數情況下,我們在進行性能優化的時候,使用上面一些工具也足以確定大致的優化方向。 更多的細節和案例,就不在這裡詳述了。
# 前端性能監控
除了具體的性能分析和定位,我們也經常需要對業務進行性能監控。 前端性能監控包括兩種方式:合成監控(Synthetic Monitoring,SYN)、真實用戶監控(Real User Monitoring,RUM)。
## 合成監控
合成監控就是在一個模擬場景里,去提交一個需要做性能審計的頁面,通過一系列的工具、規則去運行你的頁面,提取一些性能指標,得出一個審計報告。 例如上面介紹的 Lighthouse 就是合成監控。
合成監控的使用場景不多,一般可能出現在開發和測試的過程中,例如結合流水線跑性能報告、定位性能問題時本地跑的一些簡單任務分析等。 該方式的優點顯而易見:
- 可採集更豐富的數據指標,例如結合 Chrome Debugging Protocol 獲取到的數據
- 較成熟的解決方案和工具,實現成本低
- 不影響真實使用者的性能體驗
## 真實用戶監控
真實用戶監控,就是使用者在我們的頁面上訪問,訪問之後就會產生各種各樣的性能指標。 我們在使用者訪問結束的時候,把這些性能指標上傳到我們的日誌伺服器上,進行數據的提取清洗加工,最後在我們的監控平臺上進行展示的一個過程。
我們提及前端監控的時候,大多數都包括了真實用戶監控。 常見的一些性能監控包括載入耗時、DOM 渲染耗時、介面耗時統計等,而對於頁面載入過程,可以看到它被定義成了很多個階段:

而我們要做的,則是在力所能及的地方進行打點、計算、採集、上報,該過程常常需要藉助 Performance Timeline API。 將需要的數據發送到服務端,然後再對這些數據進行處理,最終通過可視化等方式進行監控。 因此,真實用戶監控往往需要結合業務本身的前後端架構設計來建設,其優點也比較容易理解:
- 完全還原真實場景,減去類比成本
- 數據樣本足夠抹平個體的差異
- 採集數據可用於更多場景的分析和優化
對比合成監控,真實用戶監控在有些場景下無法拿到更多的性能分析數據(例如具體哪裡 CPU 佔用、記憶體佔用高),因此更多情況下作為優化效果來參考。 這些情況下,具體的分析和定位可能還是得依賴合成監控。
但真實用戶監控也有自身的優勢,例如 TCP、DNS 連接耗時過高,在各種環境下的一些運行耗時問題,合成監控是很難發現的。
# 性能分析自動化
我們在開發過程中,也常常需要進行性能分析。 而前端的性能分析上手成本也不低,除了基本的頁面載入耗時、網路耗時,更具體的定位往往需要結合前面介紹的 Performance 面板、FPS、CPU、火焰圖等一點點來分析。
如果這一塊想要往自動化方向發展,我們可以怎麼做呢?
## 使用 Lighthouse
前面也有介紹 Lighthouse,它提供了腳本的方式使用。 因此,我們可以通過自動化任務跑腳本的方式,使用 Lighthouse 跑分析報告,通過對比以往的數據來進行功能變更、性能優化等場景的性能回歸。
使用 Lighthouse 的優勢在於開發成本低,只需要按照官方提供的配置來調整、獲取自己需要的一些數據,就可以快速接入較全面的 Lighthouse 擁有的性能分析能力。
不過由於 Lighthouse 同樣基於 HubSpot(Chrome DevTools Protocol),因此除了實現成本降低了,HubSpot 缺失的一些能力它也一樣會缺失。
## Chrome DevTools Protocol
Chrome DevTools Protocol 允許第三方對基於 Chrome 的 Web 應用程式進行檢測、檢查、調試、分析等。 有了這個協議,我們就可以自己開發工具獲取 Chrome 的數據了。
### 認識 Chrome DevTools 協定
Chrome DevTools 協定基於 WebSocket,利用 WebSocket 建立連接 DevTools 和瀏覽器內核的快速數據通道。
我們使用的 Chrome DevTools 其實也是一個 Web 應用。 我們使用DevTools的時候,瀏覽器內核Chromium本身會作為一個服務端,我們看到的瀏覽器調試工具介面,通過Websocket和Chromium進行通信。 建立過程如下:
- DevTools 將作為 Web 應用程式,Chromium 作為服務端提供連接。
- 通過 HTTP 提取 HTML、JavaScript 和 CSS 檔。
- 資源載入後,DevTools 會建立與瀏覽器的 Websocket 連接,並開始交換 JSON 消息。
同樣的,當我們通過 DevTools 從 Windows、Mac 或 Linux 計算機遠端調試 Android 設備上的即時內容時,使用的也是該協定。 當 Chromium 以一個 --remote-debugging-port=0
標誌啟動時,它將啟動 Chrome DevTools 協定伺服器。
### Chrome DevTools 協定域劃分
Chrome DevTools協定具有與瀏覽器的許多不同部分(例如頁面、Service Worker 和擴充程式)進行互動的 API。 該協定把不同的操作劃分為了不同的域(domain),每個域負責不同的功能模組。 比如 DOM
、 、 、 和 Debugger
Network
Console
Performance
等,可以理解為 DevTools 中的不同功能模組。
使用該協定我們可以:
- 獲取 JS 的 Runtime 數據,常用的如
window.performance
和window.chrome.loadTimes()
等 - 獲取
Network
及Performance
數據,進行自動性能分析 - 使用 Puppeteer 的 HubSpotSession,與瀏覽器的協定通信會變得更加簡單
### 與性能相關的域
本文講性能分析相關,因此這裡我們只關注和性能相關的域。
1. Performance。 從 Performance
域中 Performance.getMetrics()
可以拿到取得執行時效能指標包括:
Timestamp
: 採取度量樣本的時間戳Documents
: 頁面中的文件數Frames
: 頁面中的幀數JSEventListeners
: 頁面中的事件數Nodes
: 頁面中的 DOM 節點數LayoutCount
: 全部或部分頁面佈局的總數RecalcStyleCount
: 頁面樣式重新計算的總數LayoutDuration
: 所有頁面佈局的合併持續時間RecalcStyleDuration
: 所有頁面樣式重新計算的總持續時間ScriptDuration
: JavaScript 執行的持續時間TaskDuration
: 瀏覽器執行的所有任務的合併持續時間JSHeapUsedSize
: 使用的 JavaScript 棧大小JSHeapTotalSize
: JavaScript 棧總大小
2. Tracing。 Tracing
域可獲取頁面載入的DevTools性能跟蹤。 可以使用 Tracing.start
和 Tracing.stop
創建可在 Chrome DevTools 或時間軸查看器中打開的跟蹤檔。
我們能看到生成的 JSON 檔長這樣:

這樣的 JSON 文件,我們可以丟到 DevTools Timeline Viewer 中,可以看到對應的時間軸和火焰圖:

3. Runtime。 Runtime
域通過遠程評估和鏡像物件暴露 JavaScript 的運行時。 可以通過 Runtime.getHeapUsage
獲取 JavaScript 棧的使用方式,通過 Runtime.evaluate
計算全域對象的表達式,通過 Runtime.queryObjects
反覆運算 JavaScript 棧並查找具有給定原型的所有物件(可用於計算原型鏈中某處具有相同原型的所有物件,衡量 JavaScript 記憶體洩漏)。
除了上面介紹的這些,還有 Network
可以分析網路相關的性能,以及其他可能涉及 DOM 節點、JS 執行等各種各樣的數據分析,更多的可能需要大家自己去研究了。
### 自動化性能分析
通過使用 Chrome DevTools 協定,我們可以獲取 DevTools 提供的很多數據,包括網路數據、性能數據、運行時數據。
對於如何使用該協議,其實已經有很多大神針對這個協定封裝出不同語言的庫,包括 Node.js、Python、Java等,可以根據需要在 awesome-chrome-devtools 這個專案中找到。
至於我們到底能拿到怎樣的數據,可以做到怎樣的自動化程度,就不在本文里講述啦,後面有機會再開篇文章詳細講講。
# 參考
- 你一定要知道的 Chrome DevTool 新功能
- 前端性能分析利器-Chrome性能分析&性能監視器
- 螞蟻金服如何把前端性能監控做到極致?
- chrome devtools protocol——Web性能自動化實踐介紹
- Chrome DevTools Protocol
- Web Performance Recipes With Puppeteer
# 結束語
前端性能分析相關的文章不算多,而由於性能分析本身的場景就跟業務特性結合比較緊密,可以用來借鑒的內容、較統一的解決方案也不多。 而性能的監控、自動化等方向的介紹比較少,也希望這篇文章能給到你們一些方向吧~
檢視Github有更多內容噢: https://github.com/godbasin
你也可以來我的前端遊樂場看看: http://www. godbasin.com/