使用性能API快速分析web前端性能

頁面的性能問題一直是產品開發過程當中的重要一環,不少公司也一直在使用各類方式監控產品的頁面性能。從控制檯工具、Fiddler抓包工具,到使用DOMContentLoadeddocument.onreadystatechange這種侵入式javascript代碼方式來檢測DOM事件發生和結束的時間,再到使用第三方工具如WebPagetestPingdom等經過在不一樣的瀏覽器環境和地域進行測試來尋求優化建議等等,這些方式不只麻煩,並且測量的指標比較單一。若是有一些能夠幫咱們直接獲取頁面性能信息的API出現,而且成爲標準被被瀏覽器廠商支持,那性能監控會不會又是另外一幅藍圖?javascript

好在W3C Web性能工做小組與各瀏覽器廠商都已認識到性能對於web開發的重要性,爲了解決當前性能測試的困難,W3C推出了一套性能API標準,各類瀏覽器對這套標準的支持現在也逐漸成熟起來。這套API的目的是簡化開發者對網站性能進行精確分析與控制的過程,方便開發者採起手段提升web性能。html

整套標準包含了10餘種API,各自針對性能檢測的某個方面。在下圖中能夠看到它們當前在規範流程中的進展:前端

API進展

下面是API及描述其功能的列表:

API 名稱 功能
Navigation Timing 導航計時 可以幫助網站開發者檢測真實用戶數據(RUM),例如帶寬、延遲或主頁的總體頁面加載時間。
Resource Timing 資源計時 對單個資源的計時,能夠對細粒度的用戶體驗進行檢測。
High Resolution Timing 高精度計時 該API規範所定義的JavaScript接口可以提供精確到微秒級的當前時間,而且不會受到系統時鐘誤差或調整的影響。
Page Visibility 頁面可見性 經過這一規範,網站開發者可以以編程方式肯定頁面的當前可見狀態,從而使網站可以更有效地利用電源與CPU。當頁面得到或失去焦點時,文檔對象的visibilitychange事件便會被觸發。
Performance Timeline 性能時間線 以一個統一的接口獲取由Navigation Timing、Resourcing Timing和User Timing所收集的性能數據。
Battery Status 電池狀態 可以檢測當前設備的電池狀態,例如是否正在充電、電量等級。能夠根據當前電量決定是否顯示某些內容,對於移動設備來講很是實用。
User Timing 用戶計時 能夠對某段代碼、函數進行自定義計時,以瞭解這段代碼的具體運行時間。
Beacon 燈塔 能夠將分析結果或診斷代碼發送給服務器,它採用了異步執行的方式,所以不會影響頁面中其它代碼的運行。
Animation Timing 動畫計時 經過requestAnimationFrame函數讓瀏覽器精通地控制動畫的幀數,可以有效地配合顯示器的刷新率,提供更平滑的動畫效果,減小對CPU和電池的消耗。
Resource Hits 資源提示 經過html屬性指定資源的預加載,例如在瀏覽相冊時可以預先加載下一張圖片,加快翻頁的顯示速度。
Frame Timing 幀計時 經過一個接口獲取與幀相關的性能數據,例如每秒幀數和TTF。
Navigation Error Logging 錯誤日誌記錄 經過一個接口存儲及獲取與某個文檔相關的錯誤記錄。

瀏覽器支持

下表列舉了當前主流瀏覽器對性能API的支持,其中標註星號的內容並不是來自於Web性能工做小組。java

規範 IE Firefox Chrome Safari Opera iOS Safari Android
Navigation Timing 9 31 所有 8 26 8 (不包括 8.1) 4.1
High Resolution Timing 10 31 所有 8 26 8 (不包括 8.1) 4.4
Page Visibility 10 31 所有 7 26 7.1 4.4
Resource Timing 10 34 所有 - 26 - 4.4
Battery Status* - 31(部分支持) 38 - 26 - -
User Timing 10 - 所有 - 26 - 4.4
Beacon - 31 39 - 26 - -
Animation Timing 10 31 所有 6.1 26 7.1 4.4
Resource Hints - - 僅限Canary版 - - - -
Frame Timing - - - - - - -
Navigation Error Logging - - - - - - -
WebP* - - 所有 - 26 - 4.1
Picture element and srcset attribute * - - 38 - 26 - -

其中有兩個能夠幫助咱們檢測真實用戶環境下的頁面加載Timing和頁面資源加載Timing: Navigation TimingResource Timing。這兩個API很是有用,能夠幫助咱們獲取頁面的Domready時間、onload時間、白屏時間等,以及單個頁面資源在從發送請求到獲取到rsponse各階段的性能參數。git

使用這兩個API時須要在頁面徹底加載完成以後才能使用,最簡單的辦法是在window.onload事件中讀取各類數據,由於不少值必須在頁面徹底加載以後才能得出。github

Navigation Timing

Navigation Timing API可以幫助網站開發者檢測真實用戶數據(RUM),例如帶寬、延遲或主頁的總體頁面加載時間。用法以下:web

var timinhObj = performance.timing;

performance.timing返回的是一個PerformanceTiming對象,以下圖:編程

PerformanceTiming

若是要得到 page load time(頁面加載時間),能夠用PerformanceTiming對象中loadEventStart的值減去navigationStart的值:數組

plt = page.loadEventStart - page.navigationStart;

須要注意的是,PerformanceTiming對象中各屬性值的單位均爲毫秒數。瀏覽器

PerformanceTiming對象包含了各類與瀏覽器性能有關的時間數據,提供瀏覽器處理網頁各個階段的耗時,它包含的頁面性能屬性以下表:

屬性 含義
navigationStart 準備加載新頁面的起始時間
redirectStart 若是發生了HTTP重定向,而且從導航開始,中間的每次重定向,都和當前文檔同域的話,就返回開始重定向的timing.fetchStart的值。其餘狀況,則返回0
redirectEnd 若是發生了HTTP重定向,而且從導航開始,中間的每次重定向,都和當前文檔同域的話,就返回最後一次重定向,接收到最後一個字節數據後的那個時間.其餘狀況則返回0
fetchStart 若是一個新的資源獲取被髮起,則 fetchStart必須返回用戶代理開始檢查其相關緩存的那個時間,其餘狀況則返回開始獲取該資源的時間
domainLookupStart 返回用戶代理對當前文檔所屬域進行DNS查詢開始的時間。若是此請求沒有DNS查詢過程,如長鏈接,資源cache,甚至是本地資源等。 那麼就返回 fetchStart的值
domainLookupEnd 返回用戶代理對結束對當前文檔所屬域進行DNS查詢的時間。若是此請求沒有DNS查詢過程,如長鏈接,資源cache,甚至是本地資源等。那麼就返回 fetchStart的值
connectStart 返回用戶代理向服務器服務器請求文檔,開始創建鏈接的那個時間,若是此鏈接是一個長鏈接,又或者直接從緩存中獲取資源(即沒有與服務器創建鏈接)。則返回domainLookupEnd的值
(secureConnectionStart) 可選特性。用戶代理若是沒有對應的東東,就要把這個設置爲undefined。若是有這個東東,而且是HTTPS協議,那麼就要返回開始SSL握手的那個時間。 若是不是HTTPS, 那麼就返回0
connectEnd 返回用戶代理向服務器服務器請求文檔,創建鏈接成功後的那個時間,若是此鏈接是一個長鏈接,又或者直接從緩存中獲取資源(即沒有與服務器創建鏈接)。則返回domainLookupEnd的值
requestStart 返回從服務器、緩存、本地資源等,開始請求文檔的時間
responseStart 返回用戶代理從服務器、緩存、本地資源中,接收到第一個字節數據的時間
responseEnd 返回用戶代理接收到最後一個字符的時間,和當前鏈接被關閉的時間中,更早的那個。一樣,文檔可能來自服務器、緩存、或本地資源
domLoading 返回用戶代理把其文檔的 "current document readiness" 設置爲 "loading"的時候
domInteractive 返回用戶代理把其文檔的 "current document readiness" 設置爲 "interactive"的時候.
domContentLoadedEventStart 返回文檔發生 DOMContentLoaded事件的時間
domContentLoadedEventEnd 文檔的DOMContentLoaded 事件的結束時間
domComplete 返回用戶代理把其文檔的 "current document readiness" 設置爲 "complete"的時候
loadEventStart 文檔觸發load事件的時間。若是load事件沒有觸發,那麼該接口就返回0
loadEventEnd 文檔觸發load事件結束後的時間。若是load事件沒有觸發,那麼該接口就返回0

通常來講,咱們須要獲取到的頁面性能參數包括:DNS查詢耗時、TCP連接耗時、request請求耗時、解析dom樹耗時、白屏時間、domready時間、onload時間等,而這些參數是經過上面的performance.timing各個屬性的差值組成的,計算方法以下:

DNS查詢耗時 :domainLookupEnd - domainLookupStart
TCP連接耗時 :connectEnd - connectStart
request請求耗時 :responseEnd - responseStart
解析dom樹耗時 : domComplete - domInteractive
白屏時間 :responseStart - navigationStart
domready時間 :domContentLoadedEventEnd - navigationStart
onload時間 :loadEventEnd - navigationStart

Navigation Timing的目的是用於分析頁面總體性能指標。若是要獲取個別資源(例如JS、圖片)的性能指標,就須要使用Resource Timing API

Resource Timing

瀏覽器獲取網頁時,會對網頁中每個靜態資源(腳本文件、樣式表、圖片文件等等)發出一個HTTP請求。Resource Timing能夠獲取到單個靜態資源從開始發出請求到獲取響應之間各個階段的Timing。用法以下:

var resourcesObj = performance.getEntries();

Resource Timing返回的是一個對象數組,數組的每個項都是一個對象,這個對象中包含了當前靜態資源的加載Timing,以下圖:

PerformanceTiming

咱們能夠根據數組的長度獲取到頁面中靜態資源的數量,而後經過數組的每一項分析單個靜態資源的請求狀態。

performance中還有一些性能API還沒有成爲W3C標準(如第一張圖中的工做進度),有的處於編輯草案階段,有的處於工做草案階段,當這些API逐漸成爲推薦標準之後,必定會對咱們進行前端性能監控帶來很大的便利,咱們也能夠經過這些API很方便地直接從頁面中獲取到咱們但願獲得的性能信息。

相關資源

performance API

window.performance 詳解

使用簡潔的 Navigation Timing API 測試網頁加載速度(不徹底譯文)

相關文章
相關標籤/搜索