前端性能監控

從一道經典的面試題開始

(本文部份內容整理自網絡文章)html

用戶從輸入 URL 到頁面加載完成,都發生了什麼?前端

image

  1. DNS 解析 (解析域名,將URL解析爲對應的IP地址)
  2. TCP 鏈接(與這個IP創建TCP網絡鏈接,三次握手)
  3. 發送HTTP 請求
  4. 服務端相應HTTP 返回數據
  5. 瀏覽器拿到響應數據,解析響應內容,把解析的結果展現給用戶

前端性能都包括哪些

image

這個性能劃分是我從一篇文章上扒下來的,咱們這裏主要討論性能監控vue

前端性能監控-關鍵指標

  • 首屏時間
  • 白屏時間
  • 頁面總下載時間

瀏覽器性能先關內容概述

性能方面咱們經過 window.preformance.timing 這個屬性來獲取性能相關參數react

window.preformance.timing(記錄了頁面各個狀態的時間戳)面試

image

那麼這些參數都是什麼意義,以及它們觸發機制是什麼算法

我來看一張經典的圖 canvas

image

咱們把它翻譯一下數組

【Prompt for unload】- 用戶跳轉行爲(在地址欄輸入url後按回車,或者點擊a標籤跳轉等)
 navigationStart、startTime // 當前瀏覽器窗口的前一個網頁關閉開始執行的時間戳
 unloadStart // 前一個頁面unload觸發開始時間戳
【unload】- 前一個頁面unload時間
 unloadEnd // 前一個頁面unload觸發結束時間戳
 redirectStart // 返回第一個HTTP跳轉開始時的時間戳若是沒有跳轉,或者不是同一個域名內部的跳轉,則返回值爲0
【redirect】- 重定向
 redirectEnd // 返回最後一個HTTP跳轉結束時(即跳轉回應的最後一個字節接受完成時)的時間戳,若是沒有跳轉,或者不是同一個域名內部的跳轉,則返回值爲0
 fetchStart // 返回瀏覽器準備使用HTTP請求讀取文檔時的時間戳。該事件在網頁查詢本地緩存以前發生
【App cache】- 網頁查詢本地緩存
 domainLookupStart // 返回域名查詢開始時的時間戳。若是使用持久鏈接,或者信息是從本地緩存獲取的,則返回值等同於fetchStart屬性的值
【DNS】- 域名查詢
 domainLookupEnd // 返回域名查詢結束時的時間戳。若是使用持久鏈接,或者信息是從本地緩存獲取的,則返回值等同於fetchStart屬性的值
 connectStart // 返回創建TCP連接開始向服務器發送時的時間戳。若是使用持久鏈接(persistent connection),則返回值等同於fetchStart屬性的值
【TCP】
 secureConnectionStart // 它的值是安全鏈接握手以前的時刻。若是該屬性不可用,則返回undefined。若是該屬性可用,但沒有使用HTTPS,則返回0
 connectEnd // 返回瀏覽器與服務器之間的鏈接創建時的時間戳。若是創建的是持久鏈接,則返回值等同於fetchStart屬性的值。鏈接創建指的是全部握手和認證過程所有結束
回瀏覽器與服務器開始安全連接的握手時的時間戳。若是當前網頁不要求安全鏈接,則返回0
 requestStart // 返回瀏覽器向服務器發出HTTP請求時(或開始讀取本地緩存時)的時間戳
【Request】 - 網絡請求
 responseStart // 返回瀏覽器從服務器收到(或從本地緩存讀取)第一個字節時的時間戳
【Response】
 responseEnd // 返回瀏覽器從服務器收到(或從本地緩存讀取)最後一個字節時(若是在此以前HTTP鏈接已經關閉,則返回關閉時)的時間戳
 domLoading // 返回當前網頁DOM結構開始解析時(即Document.readyState屬性變爲「loading」、相應的readystatechange事件觸發時)的時間戳
【Processing】
 domInteractive // 返回當前網頁DOM結構結束解析、開始加載內嵌資源時(即Document.readyState屬性變爲「interactive」、相應的readystatechange事件觸發時)的時間戳
 domContentLoadedEventStart // 返回當前網頁DOMContentLoaded事件發生時(即DOM結構解析完畢、全部腳本開始運行時)的時間戳
 domContentLoadedEventEnd // 返回當前網頁全部須要執行的腳本執行完成時的時間戳
 domComplete // 返回當前網頁DOM結構生成時(即Document.readyState屬性變爲「complete」,以及相應的readystatechange事件發生時)的時間戳
 loadEventStart // 返回當前網頁load事件的回調函數開始時的時間戳。若是該事件尚未發生,返回0
【onLoad】- window.onLoad觸發
 loadEventEnd // 返回當前網頁load事件的回調函數運行結束時的時間戳。若是該事件尚未發生,返回0。經過while循環持續判斷直到loadEventEnd>0則表示徹底加載完畢了!網絡再也不有任何數據請求、dom也渲染完畢了
複製代碼

注意

因爲window.preformance.timing是一個在不一樣階段,被不停修正的一個參數對象,因此,建議在window.onload中進行性能數據讀取和上報瀏覽器

關鍵數據獲取

  • 首屏時間:計算起來比較麻煩,後文會詳述
  • 白屏時間:responseEnd - navigationStart
  • 頁面總下載時間:loadEventEnd - navigationStart

其餘數據:緩存

  • DNS解析耗時:domainLookupEnd - domainLookupStart
  • TCP連接耗時:connectEnd - connectStart
  • 首包請求耗時:responseEnd - responseStart
  • dom解釋耗時:domComplete - domInteractive
  • 用戶可操做時間:domContentLoadedEventEnd - navigationStart
  • ...

首屏時間計算

目前業內對首屏時間方式並不統一,常見的有下面幾種計算方式:

  • 利用首屏中最後一張圖片加載完成的時間來當作首屏時間(適合首屏元素由服務端渲染

方法:給頁面全部的img綁定onload事件,用來記錄圖片加載時間;在window.onload中,計算每個img的offsetTop;把符合首屏高度的圖片數據收集起來,計算最大onload時間

  • 圖片類似度比較法,經過比較連續截屏圖像的像素點變化趨勢肯定首屏時間(適合異步請求數據渲染的場景

方法:經過html2canvas插件,每100ms截取屏幕;而後獲取屏幕九宮格每一格中心點的,獲取紅色通道的像素相加獲得一個值,經過不斷截屏和比較這個求和的值,監控出首屏是否加載完畢。(截屏圖像類似度比較的方法最爲科學和直觀,可是比較消耗本地設備的運行資源。並且因爲比較複雜的運算,會影響到頁面邏輯腳本執行的性能)

  • 首屏模塊標籤標記法(頁面多數異步請求渲染)

方法:在 HTML 文檔中對應首屏內容的標籤結束位置,使用內聯的 JavaScript 代碼記錄當前時間戳

  • 自定義模塊內容計算法(自定義每一個頁面太複雜)

方法:經過自定義模塊內容,來簡化計算首屏時間

  • 用onLoad或者domReady觸發時間表示首屏時間

咱們的首屏計算方式

首先咱們要介紹一下window.performance.getEntries()方法,由於後面會用到

window.performance.getEntries()

調用後會獲取頁面加載資源和網絡請求信息

image

拿到以後是個數組,裏面包含了頁面全部的靜態資源、網絡請求相關信息,咱們經過initiatorType來獲取每個元素的屬性

image

「xmlhttprequest」表示的就是接口請求

首屏計算方式

  • 默認值爲:domContentLoadedEventEnd - navigationStart
  • 若是是vue項目,採用mounted觸發時間做爲計算分界點。
  • 若是是react項目,採用componentDidMount觸發時間做爲計算分界點。
  • 遍歷window.performance.getEntries()全部內容,過濾mounted、componentDidMount以前發出的全部請求內容,若是有xmlhttprequest,則採用最後返回response的時間做爲首屏時間
  • 若是是ssr項目,直接採用默認計算方式(domContentLoadedEventEnd - navigationStart)

可能你們會有疑問,咱們首屏時間的計算中,不包含渲染和圖片加載時間?

確實,咱們這麼作有兩個前提:

  • 一般狀況下咱們認爲瀏覽器渲染時間會很快
  • 頁面加載的圖片必須進行截取(這個由各業務線本身控制)

因此這種首屏計算方式,更像是「首屏數據開始渲染時間」(由於此時已經拿到了首屏渲染全部須要的數據)

在圖片過多、過大時候是會有必定程度的偏差

咱們爲何這麼作?

  • 爲了實現自動統計,且不但願性能統計的邏輯被強制注入到的業務代碼中
  • 儘量的接近真實的首屏加載時間
  • 在不過多佔用瀏覽器首屏加載性能的狀況下完成數據收集

首屏時間目前各家公司的計算方式不盡相同,可是所採用的,必定是在符合各自公司真實狀況的前提下,最接近於首屏時間的計算方式。

其實數據準確性和收集數據的性能開銷,是一種博弈,對於公司來說,應該選擇最合適的方式。

相關文章
相關標籤/搜索