10分鐘徹底搞懂前端頁面性能監(jiān)控

本文首發(fā)于知乎《10分鐘徹底搞懂前端頁面性能監(jiān)控》,搬運(yùn)轉(zhuǎn)載請(qǐng)注明出處,否則追究版權(quán)責(zé)任。

前言

前端頁面性能是一個(gè)非常核心的用戶體驗(yàn)指標(biāo)。本文介紹阿里UC?岳鷹全景監(jiān)控平臺(tái)?如何設(shè)計(jì)一個(gè)通用、低侵入性、自動(dòng)上報(bào)的頁面性能監(jiān)控方案。主要采用的是Navigation Timing API以及sendBeacon等方法。

為什么要監(jiān)控頁面性能?

一個(gè)頁面性能差的話會(huì)大大影響用戶體驗(yàn)。用戶打開頁面等待的太久,可能會(huì)直接關(guān)掉頁面,甚至就不再使用了,這種情況在移動(dòng)端更加明顯,移動(dòng)端用戶對(duì)頁面響應(yīng)延遲容忍度很低。

雖然頁面性能很重要,但是在實(shí)際使用中,頁面性能差的情況并不少見。首先,在產(chǎn)品的迭代演進(jìn)過程中,頁面性能可能會(huì)被忽略,性能隨著版本迭代而有所衰減;其次,性能優(yōu)化是一項(xiàng)復(fù)雜而挑戰(zhàn)的事情,需要明確的優(yōu)化方向和具體的優(yōu)化手段才能快速落地取效。

所以我們需要一個(gè)性能監(jiān)控系統(tǒng),持續(xù)監(jiān)控和預(yù)警頁面性能的狀況,并且在發(fā)現(xiàn)瓶頸的時(shí)候指導(dǎo)優(yōu)化工作。

理解Navigation Timing API的性能指標(biāo)

為了幫助開發(fā)者更好地衡量和改進(jìn)前端頁面性能,W3C性能小組引入了 Navigation Timing API ,實(shí)現(xiàn)了自動(dòng)、精準(zhǔn)的頁面性能打點(diǎn);開發(fā)者可以通過?window.performance?屬性獲取。

performance.timing?接口(定義了從?navigationStart?至?loadEventEnd?的 21 個(gè)只讀屬性)

performance.navigation(定義了當(dāng)前文檔的導(dǎo)航信息,比如是重載還是向前向后等)

下圖是W3C第一版的 Navigation Timing 的處理模型。從當(dāng)前瀏覽器窗口卸載舊頁面開始,到新頁面加載完成,整個(gè)過程一共被切分為 9 個(gè)小塊:提示卸載舊文檔、重定向/卸載、應(yīng)用緩存、DNS 解析、TCP 握手、HTTP 請(qǐng)求處理、HTTP 響應(yīng)處理、DOM 處理、文檔裝載完成。每個(gè)小塊的首尾、中間做事件分界,取 Unix 時(shí)間戳,兩兩事件之間計(jì)算時(shí)間差,從而獲取中間過程的耗時(shí)(精確到毫秒級(jí)別)。

上圖是 Level 1 的規(guī)范,2012 年底進(jìn)入候選建議階段,至今仍在日常使用中;但是在W3C的議程上,它已經(jīng)功成身退,讓位給了精度更高,功能更強(qiáng)大,層次更分明的 Level 2(處理模型如下圖)。比如獨(dú)立劃分出來的 Resource Timing,使得我們可以獲取具體資源的詳細(xì)耗時(shí)信息。

指標(biāo)解讀

采集頁面性能的關(guān)鍵指標(biāo)

使用上面的指標(biāo),我們可以計(jì)算許多重要的指標(biāo),如首字節(jié)的時(shí)間,頁面加載時(shí)間,dns查找以及連接是否安全。我們把 Navigation Timing API 提供的指標(biāo)做下歸類,按照從上到下的時(shí)間流,右邊的時(shí)刻標(biāo)記了每個(gè)指標(biāo)從哪里開始計(jì)算到哪里截止,比如,跳轉(zhuǎn)時(shí)間 redirect 由?redirectEnd - redirectStart?計(jì)算得到,其他的類推。

確定統(tǒng)計(jì)起始點(diǎn) (navigationStart vs fetchStart )

頁面性能統(tǒng)計(jì)的起始點(diǎn)時(shí)間,應(yīng)該是用戶輸入網(wǎng)址回車后開始等待的時(shí)間。一個(gè)是通過navigationStart獲取,相當(dāng)于在URL輸入欄回車或者頁面按F5刷新的時(shí)間點(diǎn);另外一個(gè)是通過?fetchStart,相當(dāng)于瀏覽器準(zhǔn)備好使用 HTTP 請(qǐng)求獲取文檔的時(shí)間。

從開發(fā)者實(shí)際分析使用的場景,瀏覽器重定向、卸載頁面的耗時(shí)對(duì)頁面加載分析并無太大作用;通常建議使用?fetchStart?作為統(tǒng)計(jì)起始點(diǎn)。

首字節(jié)

主文檔返回第一個(gè)字節(jié)的時(shí)間,是頁面加載性能比較重要的指標(biāo)。對(duì)用戶來說一般無感知,對(duì)于開發(fā)者來說,則代表訪問網(wǎng)絡(luò)后端的整體響應(yīng)耗時(shí)。

白屏?xí)r間

用戶看到頁面展示出現(xiàn)一個(gè)元素的時(shí)間。很多人認(rèn)為白屏?xí)r間是頁面返回的首字節(jié)時(shí)間,但這樣其實(shí)并不精確,因?yàn)轭^部資源還沒加載完畢,頁面也是白屏。

相對(duì)來說具備「白屏?xí)r間」統(tǒng)計(jì)意義的指標(biāo),可以取?domLoading - fetchStart,此時(shí)頁面開始解析DOM樹,頁面渲染的第一個(gè)元素也會(huì)很快出現(xiàn)。

從W3C Navigation Timing Level 2 的方案設(shè)計(jì),可以直接采用?domInteractive - fetchStart?,此時(shí)頁面資源加載完成,即將進(jìn)入渲染環(huán)節(jié)。

首屏?xí)r間

首屏?xí)r間是指頁面第一屏所有資源完整展示的時(shí)間。這是一個(gè)對(duì)用戶來說非常直接的體驗(yàn)指標(biāo),但是對(duì)于前端卻是一個(gè)非常難以統(tǒng)計(jì)衡量的指標(biāo)。

具備一定意義上的指標(biāo)可以使用,domContentLoadedEventEnd - fetchStart,甚至使用loadEventStart - fetchStart,此時(shí)頁面DOM樹已經(jīng)解析完成并且顯示內(nèi)容。

以下給出統(tǒng)計(jì)頁面性能指標(biāo)的方法。

lettimes= {};let t = window.performance.timing;// 優(yōu)先使用 navigation v2? https://www.w3.org/TR/navigation-timing-2/if(typeof win.PerformanceNavigationTiming ==='function') {try{? ? var nt2Timing = performance.getEntriesByType('navigation')[0]if(nt2Timing) {? ? ? t = nt2Timing? ? }? }catch(err) {? }}//重定向時(shí)間times.redirectTime = t.redirectEnd - t.redirectStart;//dns查詢耗時(shí)times.dnsTime = t.domainLookupEnd - t.domainLookupStart;//TTFB 讀取頁面第一個(gè)字節(jié)的時(shí)間times.ttfbTime = t.responseStart - t.navigationStart;//DNS 緩存時(shí)間times.appcacheTime = t.domainLookupStart - t.fetchStart;//卸載頁面的時(shí)間times.unloadTime = t.unloadEventEnd - t.unloadEventStart;//tcp連接耗時(shí)times.tcpTime = t.connectEnd - t.connectStart;//request請(qǐng)求耗時(shí)times.reqTime = t.responseEnd - t.responseStart;//解析dom樹耗時(shí)times.analysisTime = t.domComplete - t.domInteractive;//白屏?xí)r間 times.blankTime = (t.domInteractive || t.domLoading) - t.fetchStart;//domReadyTimetimes.domReadyTime = t.domContentLoadedEventEnd - t.fetchStart;

SPA盛行之際

Navigation Timing API可以監(jiān)控大部分前端頁面的性能。但隨著SPA模式的盛行,類似vue,reactjs等框架的普及,頁面內(nèi)容渲染的時(shí)機(jī)被改變了,W3C標(biāo)準(zhǔn)無法完全滿足原來的監(jiān)控意義。

幸運(yùn)的是,目前W3C關(guān)于首屏統(tǒng)計(jì)已經(jīng)進(jìn)入了提議階段,以Chrome為首的瀏覽器正在打造更能代表用戶使用體驗(yàn)的FP、FCP、FMP指標(biāo),并且逐步開放API。

注意點(diǎn)

通過window.performance.timing所獲的的頁面渲染所相關(guān)的數(shù)據(jù),在SPA應(yīng)用中改變了url但不刷新頁面的情況下是不會(huì)更新的。因此僅僅通過該api是無法獲得每一個(gè)子路由所對(duì)應(yīng)的頁面渲染的時(shí)間。如果需要上報(bào)切換路由情況下每一個(gè)子頁面重新render的時(shí)間,需要自定義上報(bào)。

數(shù)據(jù)上報(bào)方式

測量好時(shí)間后,就需要將數(shù)據(jù)發(fā)送給服務(wù)端。頁面性能統(tǒng)計(jì)數(shù)據(jù)對(duì)丟失率要求比較低,且性能統(tǒng)計(jì)應(yīng)該在盡量不影響主流程的邏輯和頁面性能的前提下進(jìn)行。

使用的img標(biāo)簽get請(qǐng)求

不存在AJAX跨域問題,可做跨源的請(qǐng)求

很古老的標(biāo)簽,沒有瀏覽器兼容性問題

vari= new Image();i.onload =i.onerror =i.onabort =function(){i=i.onload =i.onerror =i.onabort = null;}i.src = url;

navigator.sendBeacon

大部分現(xiàn)代瀏覽器都支持 navigator.sendBeacon方法。這個(gè)方法可以用來發(fā)送一些統(tǒng)計(jì)和診斷的小量數(shù)據(jù),特別適合上報(bào)統(tǒng)計(jì)的場景。

數(shù)據(jù)可靠,瀏覽器關(guān)閉請(qǐng)求也照樣能發(fā)

異步執(zhí)行,不會(huì)影響下一頁面的加載

API使用簡單

window.addEventListener('unload',logData,false);functionlogData(){? ? navigator.sendBeacon("/log",analyticsData);}

最終方案

當(dāng)瀏覽器支持sendBeacon方法,優(yōu)先使用該方法,使用img方式降級(jí)上報(bào)。

岳鷹-WEB前端監(jiān)控

經(jīng)過1年左右時(shí)間的不斷打磨,阿里UC出品的岳鷹WEB前端監(jiān)控已經(jīng)對(duì)外開放,歡迎免費(fèi)體驗(yàn)試用。

參考

navigation-timing-2?https://www.w3.org/TR/navigation-timing-2/

Navigation API指南?https://s0developer0mozilla0org.icopy.site/en-US/docs/Web/Performance/Navigation_and_resource_timings

以用戶為中心的性能指標(biāo)?https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics?hl=zh-cn

頁面性能對(duì)業(yè)務(wù)指標(biāo)的影響?https://www.thinkwithgoogle.com/marketing-resources/data-measurement/mobile-page-speed-new-industry-benchmarks/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容