精確並自動化地獲取頁面首屏時間

本文發表在 微店前端團隊 blog前端

做者:劉遠洋git

公司:微店 - 前端團隊github

日期:2018-03-05npm

背景

在前端性能數據的獲取方法上,如今業內大多使用手動埋點的方式,即在代碼中,人工判斷首屏完成的位置,並在該處添加首屏記錄的代碼,相似:firstscreen.report() 這樣。數組

這樣作的簡單省事,但缺點也很明顯:bash

  • 和業務代碼混用dom

    通用的監控需求混入了業務代碼中前端性能

  • 覆蓋不完整函數

    須要頁面開發者自覺手動添加埋點代碼,在業務中埋點覆蓋率不必定能達到 100%工具

  • 準確性不必定高

    因爲須要開發者自行判斷統計腳本放置的位置,就會存在一些不許確的狀況,由於每一個人對首屏的理解不一樣

基於上面的分析,咱們近期嘗試了一些方案,試圖將首屏時間計算自動化,節省人力、並提升準確性。

定義

對首屏時間的定義,每一個公司可能會有所不一樣,在本文中,首屏時間指的是:

  • 若是頁面首屏有圖片

    首屏時間 = 首屏圖片所有加載完畢的時刻 - window.performance.timing.navigationStart
    複製代碼
  • 若是頁面首屏沒有圖片

    首屏時間 = 頁面處於穩定狀態前最後一次 dom 變化的時刻 - window.performance.timing.navigationStart
    複製代碼

實現原理

整體思路爲:

  • 從頁面加載開始,按照必定的間隔打點,不斷記錄各個時刻下頁面首屏圖片列表和其餘信息

    問題:按照怎樣的間隔打點?

  • 找出頁面首屏處於穩定狀態的時刻 T1(到這個時刻爲止,頁面首屏可能已經穩定了一段時間)

    問題:如何找出這個 T1?

  • 以 T1 時刻的首屏圖片數量爲準,向前倒推,找到全部打點中最後一次和 T1 時刻首屏圖片一致的打點時刻 T2

  • 統計 T2 時刻的全部圖片加載完成時間 T3

  • T3 即爲首屏完成的時刻,進行上報

下面,一個個解決上文中提到的問題:

  • 問題:如何找出首屏處於穩定狀態的時刻 T1?

    咱們將頁面從加載到渲染分爲兩大階段:1. 獲取數據;2. 數據獲取完畢,渲染頁面。

    這個邏輯符合絕大部分的頁面邏輯:先獲取數據,再渲染頁面。

    解決方案:

    1. 經過 AOP 切面方式監聽 XHR 的 send 對象,抓取頁面中的第一個 XHR 請求,以第一個 XHR 請求發出的時刻爲起點,統計在 1000ms 之內全部發出的請求到數組 Request 中。

      咱們認爲可能影響首屏的請求在 [第一個 xhr 請求發出的時刻,第一個 xhr 請求發出的時刻 + 1000ms] 的時間段內均已發出。

    2. 針對串聯型的請求(即下一個請求依賴上一個請求的返回數據),同時統計每一個請求返回後,500ms 之內新發出的請求到數組 Request 中。

      有些頁面的數據請求方式是串行的,可能通過兩個串聯的請求後首屏的數據才能加載。

      影響首屏的請求可能也會以這樣的形式發出。

    3. 數組 Request 中統計到的請求,基本包含了全部影響首屏的數據請求,同時也包含了部分不影響首屏的數據請求。

    4. 針對上述統計到的請求,找到全部數據返回的時刻 T1,而後,T1 = T1 + 300ms,保證頁面接收數據後渲染完畢(300ms 用於一次渲染足夠了)。

    5. 此時的 T1 時刻,頁面首屏被認爲處於穩定狀態。

  • 問題:按照怎樣的間隔打點?

    • MutationObserver

      你們都知道 MutationObserver 對象用於捕捉頁面 dom 變化,所以在腳本中,咱們使用了 MutationObserver 監聽 dom 變化,並在每次 dom 變化時觸發一次打點(統計該時刻首屏圖片信息)

    • setInterval

      setInterval 也能實現定時打點

    • MutationObserver 和 setInterval 組合

      但 MutationObserver 回調函數的觸發時機開發者並不可控,有幾種狀況:

      • 兩次回調之間可能距離幾百毫秒甚至 1秒多,致使統計偏差較大
      • 某些狀況下,dom 再也不變化,但頁面元素中,imgsrc 發生了變化或元素的 background-image 發生了變化,並不會觸發在 MutationObserver 的回調,致使統計失誤

      所以,咱們如今的方案是結合 MutationObserver 和 setInterval,在 MutationObserver 回調的間歇,啓動 setInterval,保證頁面加載過程當中打點間隔不會過長,提升統計準確率。

統計偏差

即便使用了上述複雜的打點與判斷,偏差仍然存在,那麼,偏差到底在哪裏?

以下圖所示:

不穩定狀態(1 images)   穩定狀態2(2 images)      穩定狀態1(2 images)
    |                        |                       |
    |________________________|_______________________|
    t1                       t2                      t3
複製代碼

按照上面的理論,咱們會取 t2 時刻爲能夠統計首屏的時刻,兩張圖片加載完成的時刻即爲首屏完成的時刻。

t2t1 時刻差了 1 張圖片。

按照咱們的理論,首屏完成時間必定在 t2 以後的某個時刻 t2.n

而實際相差的那張圖片,何時加載完成的,咱們不得而知,可能在 t2 前已經加載完畢了,也可能已經發出請求,但還沒加載完畢。

偏差就在這裏,它總會存在。

但咱們須要統計的是在偏差能夠接受範圍內的首屏數據,根據在公司業務實踐的反饋來看,數據可靠性很高。

Talk is cheap, show me the code

咱們也開源了這個小工具:

github: auto-compute-first-screen-time

npm: auto-compute-first-screen-time

歡迎小夥伴們使用,吐槽,改進。

相關文章
相關標籤/搜索