摘要:如何自動獲取首屏?xí)r間作者劉遠洋公司微店前端團隊日期本文發(fā)表在微店前端團隊背景在前端性能數(shù)據(jù)的獲取方法上,現(xiàn)在業(yè)內(nèi)大多使用手動埋點的方式,即在代碼中,人工判斷首屏完成的位置,并在該處添加首屏記錄的代碼,類似這樣。
如何自動獲取首屏?xí)r間
作者:劉遠洋
公司:微店 - 前端團隊
日期:2018-03-05
本文發(fā)表在 微店前端團隊 blog
背景在前端性能數(shù)據(jù)的獲取方法上,現(xiàn)在業(yè)內(nèi)大多使用手動埋點的方式,即在代碼中,人工判斷首屏完成的位置,并在該處添加首屏記錄的代碼,類似:firstscreen.report() 這樣。
這樣做的簡單省事,但缺點也很明顯:
和業(yè)務(wù)代碼混用
通用的監(jiān)控需求混入了業(yè)務(wù)代碼中
覆蓋不完整
需要頁面開發(fā)者自覺手動添加埋點代碼,在業(yè)務(wù)中埋點覆蓋率不一定能達到 100%
準(zhǔn)確性不一定高
由于需要開發(fā)者自行判斷統(tǒng)計腳本放置的位置,就會存在一些不準(zhǔn)確的情況,因為每個人對首屏的理解不同
基于上面的分析,我們近期嘗試了一些方案,試圖將首屏?xí)r間計算自動化,節(jié)省人力、并提高準(zhǔn)確性。
定義對首屏?xí)r間的定義,每個公司可能會有所不同,在本文中,首屏?xí)r間指的是:
如果頁面首屏有圖片
首屏?xí)r間 = 首屏圖片全部加載完畢的時刻 - window.performance.timing.navigationStart
如果頁面首屏沒有圖片
首屏?xí)r間 = 頁面處于穩(wěn)定狀態(tài)前最后一次 dom 變化的時刻 - window.performance.timing.navigationStart實現(xiàn)原理
總體思路為:
從頁面加載開始,按照一定的間隔打點,不斷記錄各個時刻下頁面首屏圖片列表和其他信息
問題:按照怎樣的間隔打點?
找出頁面首屏處于穩(wěn)定狀態(tài)的時刻 T1(到這個時刻為止,頁面首屏可能已經(jīng)穩(wěn)定了一段時間)
問題:如何找出這個 T1?
以 T1 時刻的首屏圖片數(shù)量為準(zhǔn),向前倒推,找到所有打點中最后一次和 T1 時刻首屏圖片一致的打點時刻 T2
統(tǒng)計 T2 時刻的所有圖片加載完成時間 T3
T3 即為首屏完成的時刻,進行上報
下面,一個個解決上文中提到的問題:
問題:如何找出首屏處于穩(wěn)定狀態(tài)的時刻 T1?
我們將頁面從加載到渲染分為兩大階段:1. 獲取數(shù)據(jù);2. 數(shù)據(jù)獲取完畢,渲染頁面。
這個邏輯符合絕大部分的頁面邏輯:先獲取數(shù)據(jù),再渲染頁面。
解決方案:
通過 AOP 切面方式監(jiān)聽 XHR 的 send 對象,抓取頁面中的第一個 XHR 請求,以第一個 XHR 請求發(fā)出的時刻為起點,統(tǒng)計在 1000ms 以內(nèi)所有發(fā)出的請求到數(shù)組 Request 中。
我們認(rèn)為可能影響首屏的請求在 [第一個 xhr 請求發(fā)出的時刻,第一個 xhr 請求發(fā)出的時刻 + 1000ms] 的時間段內(nèi)均已發(fā)出。
針對串聯(lián)型的請求(即下一個請求依賴上一個請求的返回數(shù)據(jù)),同時統(tǒng)計每個請求返回后,500ms 以內(nèi)新發(fā)出的請求到數(shù)組 Request 中。
有些頁面的數(shù)據(jù)請求方式是串行的,可能經(jīng)過兩個串聯(lián)的請求后首屏的數(shù)據(jù)才能加載。
影響首屏的請求可能也會以這樣的形式發(fā)出。
數(shù)組 Request 中統(tǒng)計到的請求,基本包含了所有影響首屏的數(shù)據(jù)請求,同時也包含了部分不影響首屏的數(shù)據(jù)請求。
針對上述統(tǒng)計到的請求,找到所有數(shù)據(jù)返回的時刻 T1,然后,T1 = T1 + 300ms,保證頁面接收數(shù)據(jù)后渲染完畢(300ms 用于一次渲染足夠了)。
此時的 T1 時刻,頁面首屏被認(rèn)為處于穩(wěn)定狀態(tài)。
問題:按照怎樣的間隔打點?
MutationObserver
大家都知道 MutationObserver 對象用于捕捉頁面 dom 變化,因此在腳本中,我們使用了 MutationObserver 監(jiān)聽 dom 變化,并在每次 dom 變化時觸發(fā)一次打點(統(tǒng)計該時刻首屏圖片信息)
setInterval
setInterval 也能實現(xiàn)定時打點
MutationObserver 和 setInterval 組合
但 MutationObserver 回調(diào)函數(shù)的觸發(fā)時機開發(fā)者并不可控,有幾種情況:
兩次回調(diào)之間可能距離幾百毫秒甚至 1秒多,導(dǎo)致統(tǒng)計誤差較大
某些情況下,dom 不再變化,但頁面元素中,img 的 src 發(fā)生了變化或元素的 background-image 發(fā)生了變化,并不會觸發(fā)在 MutationObserver 的回調(diào),導(dǎo)致統(tǒng)計失誤
因此,我們現(xiàn)在的方案是結(jié)合 MutationObserver 和 setInterval,在 MutationObserver 回調(diào)的間歇,啟動 setInterval,保證頁面加載過程中打點間隔不會過長,提高統(tǒng)計準(zhǔn)確率。
統(tǒng)計誤差即使使用了上述復(fù)雜的打點與判斷,誤差仍然存在,那么,誤差到底在哪里?
如下圖所示:
不穩(wěn)定狀態(tài)(1 images) 穩(wěn)定狀態(tài)2(2 images) 穩(wěn)定狀態(tài)1(2 images) | | | |________________________|_______________________| t1 t2 t3
按照上面的理論,我們會取 t2 時刻為可以統(tǒng)計首屏的時刻,兩張圖片加載完成的時刻即為首屏完成的時刻。
t2 和 t1 時刻差了 1 張圖片。
按照我們的理論,首屏完成時間一定在 t2 之后的某個時刻 t2.n。
而實際相差的那張圖片,什么時候加載完成的,我們不得而知,可能在 t2 前已經(jīng)加載完畢了,也可能已經(jīng)發(fā)出請求,但還沒加載完畢。
誤差就在這里,它總會存在。
但我們需要統(tǒng)計的是在誤差可以接受范圍內(nèi)的首屏數(shù)據(jù),根據(jù)在公司業(yè)務(wù)實踐的反饋來看,數(shù)據(jù)可靠性很高。
Talk is cheap, show me the code我們也開源了這個小工具:
github: auto-compute-first-screen-time
npm: auto-compute-first-screen-time
歡迎小伙伴們使用,吐槽,改進。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/93158.html
摘要:經(jīng)過一系列優(yōu)化后,在平臺上,點擊到頁面首屏展示的耗時從平均多降低為,優(yōu)化以上。而現(xiàn)在頁面為了更好地為用戶推薦喜歡的內(nèi)容,我們后臺引入機器學(xué)習(xí)和隨機算法來做智能個性化推薦。另外還有部分的內(nèi)容是隨機算法推薦的。 VasSonic成長歷程 前言 2017.8.8 14時,SNG增值產(chǎn)品部Vas團隊研發(fā)的輕量級高性能Hybrid框架VasSonic通過了公司最終審核,作為騰訊開源組件分享給大...
摘要:關(guān)于首屏首屏?xí)r間是指從轉(zhuǎn)向該頁面到屏幕中該頁面所有內(nèi)容都可見時的時間。如在事件處理函數(shù)中,計算高度,如果大于屏幕高度則意味著首屏的結(jié)構(gòu)已渲染完畢,開始計算首屏?xí)r間。 關(guān)于首屏 首屏?xí)r間是指從轉(zhuǎn)向該頁面到屏幕中該頁面所有內(nèi)容都可見時的時間。已經(jīng)有太多的關(guān)于首屏?xí)r間的計算,在本文中并不重復(fù)闡述這些已經(jīng)被提出或者實現(xiàn)的方案,而旨在探索與討論更多的首屏自動化采集方案,擴大思考范圍,你我思想之間...
摘要:關(guān)于首屏首屏?xí)r間是指從轉(zhuǎn)向該頁面到屏幕中該頁面所有內(nèi)容都可見時的時間。如在事件處理函數(shù)中,計算高度,如果大于屏幕高度則意味著首屏的結(jié)構(gòu)已渲染完畢,開始計算首屏?xí)r間。 關(guān)于首屏 首屏?xí)r間是指從轉(zhuǎn)向該頁面到屏幕中該頁面所有內(nèi)容都可見時的時間。已經(jīng)有太多的關(guān)于首屏?xí)r間的計算,在本文中并不重復(fù)闡述這些已經(jīng)被提出或者實現(xiàn)的方案,而旨在探索與討論更多的首屏自動化采集方案,擴大思考范圍,你我思想之間...
閱讀 1690·2021-11-23 10:07
閱讀 2682·2019-08-30 11:10
閱讀 2871·2019-08-29 17:08
閱讀 1811·2019-08-29 15:42
閱讀 3212·2019-08-29 12:57
閱讀 2424·2019-08-28 18:06
閱讀 3576·2019-08-27 10:56
閱讀 416·2019-08-26 11:33