VUE(nuxt)項目性能監(jiān)測統(tǒng)計

最近有個需求是監(jiān)測性能,要求在移動端項目里統(tǒng)計控制臺(如下圖)最后一行的Finish甚垦,DOMContentLoaded和Load三個時間茶鹃。

控制臺截圖

一、指標解釋

(1)Finish

  • Finish 時間是頁面上所有 http 請求發(fā)送到響應(yīng)完成的時間制轰,HTTP1.0/1.1 協(xié)議限定前计,單個域名的請求并發(fā)量是 6 個,即Finish是所有請求(不只是XHR請求垃杖,還包括DOC男杈,img,js调俘,css等資源的請求)在并發(fā)量為6的限制下完成的時間伶棒。

  • 頁面發(fā)送請求和頁面解析文檔結(jié)構(gòu),分屬兩個不同的線程彩库,所以 Finish 時間與DOMContentLoaded 和 Load 并無直接關(guān)系肤无。

  • Finish 的時間比 Load 大,意味著頁面有相當(dāng)部分的請求量骇钦,F(xiàn)inish 的時間比 Load 小宛渐,意味著頁面請求量很少,如果頁面是只有一個 html文檔請求的靜態(tài)頁面眯搭,F(xiàn)inish時間基本就等于HTML文檔請求的時間窥翩。

(2)DOMContentLoaded

  • 對應(yīng)頁面DOMContentLoaded事件觸發(fā)的時間點:DOM樹構(gòu)建完成。即HTML頁面由上向下解析HTML結(jié)構(gòu)到末尾封閉標簽</html> 鳞仙。

(3)Load

  • 對應(yīng)頁面Load事件觸發(fā)的時間點:頁面加載完畢寇蚊。 DOM樹構(gòu)建完成后,繼續(xù)加載html/css 中的圖片資源等外部資源棍好,加載完成后視為頁面加載完畢仗岸。

二、http請求過程及網(wǎng)頁渲染原理

(1)http請求過程

image

(2)渲染原理

image

當(dāng)我們在瀏覽器地址輸入URL時借笙,瀏覽器會發(fā)送請求到服務(wù)器扒怖,服務(wù)器將請求的HTML文檔發(fā)送回瀏覽器,瀏覽器將文檔下載下來后业稼,便開始從上到下解析盗痒,解析完成之后,會生成DOM盼忌。如果頁面中有css积糯,會根據(jù)css的內(nèi)容形成CSSOM,然后DOM和CSSOM會生成一個渲染樹谦纱,最后瀏覽器會根據(jù)渲染樹的內(nèi)容計算出各個節(jié)點在頁面中的確切大小和位置看成,并將其繪制在瀏覽器上。

html的解析又會被js打斷跨嘉,解析過程中遇到<script>標簽的時候川慌,便會停止解析過程,轉(zhuǎn)而去處理腳本祠乃,如果腳本是內(nèi)聯(lián)的梦重,瀏覽器會先去執(zhí)行這段內(nèi)聯(lián)的腳本,如果是外鏈的亮瓷,那么先會去加載腳本琴拧,然后執(zhí)行。在處理完腳本之后嘱支,瀏覽器便繼續(xù)解析HTML文檔蚓胸。(所以一般js文件放到最后面)

而在現(xiàn)在瀏覽器中,為了減緩渲染被阻塞的情況除师,現(xiàn)代的瀏覽器都使用了猜測預(yù)加載沛膳。當(dāng)解析被阻塞的時候,瀏覽器會有一個輕量級的HTML(或CSS)掃描器(scanner)繼續(xù)在文檔中掃描汛聚,查找那些將來可能能夠用到的資源文件的url锹安,在渲染器使用它們之前將其下載下來,并且下載是可以并行進行的倚舀,并行的上限一般為6叹哭。

三、Performance API

具體參考js標準教程Performance API

主要用到的是performance.timing對象瞄桨,具體解釋見上面的鏈接话速,下面這張圖對應(yīng)各個指標的時間點。


PerformanceNavigationTiming 過程

參考這段代碼的統(tǒng)計指標

(function  performanceStatistics(){

  var performance = window.performance;

  if (!performance) {
      // 當(dāng)前瀏覽器不支持
      console.log('你的瀏覽器不支持 performance 接口');
      return ;
  }
  var timing = performance.timing;
  // 如果我們需要盡量對頁面加載周期的數(shù)據(jù)進行詳細的統(tǒng)計分析:
  console.log('統(tǒng)計模塊性能時間:'); // 寫出具體模塊名稱
  console.log('準備新頁面時間耗時: ' + (timing.fetchStart - timing.navigationStart) + 'ms');
  console.log('Appcache 耗時: ' + (timing.domainLookupStart - timing.fetchStart)+ 'ms');
  console.log('DNS 查詢耗時: ' + (timing.domainLookupEnd - timing.domainLookupStart)+ 'ms');
  console.log('TCP連接耗時: ' + (timing.connectEnd - timing.connectStart)+ 'ms');
  console.log('request請求耗時: ' + (timing.responseEnd - timing.requestStart)+ 'ms');
  console.log('請求完畢至DOM加載: ' + (timing.domInteractive - timing.responseEnd)+ 'ms');
  console.log('解釋dom樹耗時: ' + ( timing.domComplete - timing.domInteractive)+ 'ms');
  console.log('load事件耗時: ' + ( timing.loadEventEnd - timing.loadEventStart)+ 'ms');
  console.log('從開始至load完成: ' + ( timing.loadEventEnd - timing.navigationStart)+ 'ms');
  console.log('頁面加載耗時: ' + ( timing.loadEventStart - timing.navigationStart)+ 'ms');
  // 至此芯侥,我們可以將頁面加載過程中的相關(guān)耗時詳盡的統(tǒng)計輸出泊交,分析耗時較長的地方并作出相關(guān)的優(yōu)化。
})()

因為是持久鏈接柱查,所以domainLookupStart廓俭、domainLookupEnd、connectEnd都等于fetchStart唉工,所以Appcache 耗時研乒、DNS 查詢耗時、TCP連接耗時都是0淋硝。

最后整出來3個指標:第一個對應(yīng)控制臺的DOMContentLoaded雹熬,第三個對應(yīng)控制臺的Load

DOM加載時間(timing.domContentLoadedEventStart - timing.navigationStart)
請求時間(timing.responseEnd - timing.requestStart)
頁面加載時間(timing.loadEventStart - timing.navigationStart)

統(tǒng)計代碼如下:

function performance(){
    var performance = window.performance;
    if (!performance) {return ;} 
    var path = window.location.pathname.replace(/(\d+)/g, '') , 
    timing = performance.timing, 
    DOMLoaded = timing.domContentLoadedEventStart - timing.navigationStart , 
    requestTime = timing.responseEnd - timing.requestStart , 
    pageLoaded = timing.loadEventStart - timing.navigationStart ; 
    _czc.push(['_trackEvent', 'DOMLoaded-time', 'show', path , DOMLoaded, '']) ;
    _czc.push(['_trackEvent', 'requestTime-time', 'show',path, requestTime, '']) ; 
    _czc.push(['_trackEvent', 'pageLoaded-time', 'show', path, pageLoaded, '']) ;
}

四宽菜、監(jiān)測代碼加在哪兒

這個是個坑,因為項目采用的是nuxt(vue)的竿报,單頁面铅乡,但是每個頁面都需要統(tǒng)計這些數(shù)據(jù),想寫在全局烈菌。試了好多方案阵幸,最后選了一種。

方案1:在mounted里寫
剛開始在首頁試的芽世,發(fā)現(xiàn)要寫在window.onload里才能統(tǒng)計到真實數(shù)據(jù)挚赊。因為是單頁面,就算在每個頁面里寫onload济瓢,取到的也都是一樣的數(shù)荠割。

方案2:中間件
這個可以寫在全局,但是路由跳轉(zhuǎn)的時候取不到window旺矾,設(shè)置延時或window.onload也不行涨共。

方案3:插件
寫了個js文件,nuxt.config.js配置了ssr: false宠漩,設(shè)置延時或window.onload還是不行举反。

方案4:nuxt.config.js加在script標簽里。這個方案是可行的扒吁,能檢測到第一次進入頁面時的數(shù)據(jù)或者是刷新當(dāng)前頁面的數(shù)據(jù)火鼻。

{ innerHTML: "window.onload = function(){var performance = window.performance;if (!performance) {return ;} var path = window.location.pathname.replace(/(\d+)/g, '') , timing = performance.timing, DOMLoaded = timing.domContentLoadedEventStart - timing.navigationStart , requestTime = timing.responseEnd - timing.requestStart , pageLoaded = timing.loadEventStart - timing.navigationStart ; _czc.push(['_trackEvent', 'DOMLoaded-time', 'show', path , DOMLoaded, '']) ; _czc.push(['_trackEvent', 'requestTime-time', 'show',path, requestTime, '']) ; _czc.push(['_trackEvent', 'pageLoaded-time', 'show', path, pageLoaded, '']);}"}

即:

window.onload = function(){
    var performance = window.performance;
    if (!performance) {return ;} 
    var path = window.location.pathname.replace(/(\\d+)/g, '') , 
    timing = performance.timing, 
    DOMLoaded = timing.domContentLoadedEventStart - timing.navigationStart , 
    requestTime = timing.responseEnd - timing.requestStart , 
    pageLoaded = timing.loadEventStart - timing.navigationStart ; 
    _czc.push(['_trackEvent', 'DOMLoaded-time', 'show', path , DOMLoaded, '']) ;
    _czc.push(['_trackEvent', 'requestTime-time', 'show',path, requestTime, '']) ; 
    _czc.push(['_trackEvent', 'pageLoaded-time', 'show', path, pageLoaded, '']) ;
}

遇到的問題:
1、var path = window.location.pathname.replace(/(\d+)/g, '') 這段代碼在瀏覽器控制臺能起效雕崩,但是統(tǒng)計數(shù)據(jù)里還是會帶著后面的參數(shù)id魁索。
發(fā)現(xiàn)是轉(zhuǎn)義了匹配上了字母d。盼铁。粗蔚。要加個轉(zhuǎn)義符\

2、統(tǒng)計數(shù)據(jù)并不全饶火,不是所有的頁面都能統(tǒng)計全3個指標鹏控,猜想是因為跳轉(zhuǎn)影響了友盟統(tǒng)計。

這個戳單頁面數(shù)據(jù)采集
如果需要準確的數(shù)據(jù)肤寝,可能需要重寫 history.replaceState 在方法当辐,在里面加上自定義的統(tǒng)計。

參考

https://segmentfault.com/q/1010000011840948/a-1020000011947156
https://www.cnblogs.com/caizhenbo/p/6679478.html
https://blog.csdn.net/TMQ1225/article/details/80454066
https://www.kancloud.cn/kancloud/javascript-standards-reference/46507#performancegetEntries_137

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鲤看,一起剝皮案震驚了整個濱河市缘揪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖找筝,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蹈垢,死亡現(xiàn)場離奇詭異,居然都是意外死亡袖裕,警方通過查閱死者的電腦和手機耘婚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陆赋,“玉大人,你說我怎么就攤上這事嚷闭≡艿海” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵胞锰,是天一觀的道長灾锯。 經(jīng)常有香客問我,道長嗅榕,這世上最難降的妖魔是什么顺饮? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮凌那,結(jié)果婚禮上兼雄,老公的妹妹穿的比我還像新娘。我一直安慰自己帽蝶,他們只是感情好赦肋,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著励稳,像睡著了一般佃乘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上驹尼,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天趣避,我揣著相機與錄音,去河邊找鬼新翎。 笑死程帕,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的地啰。 我是一名探鬼主播骆捧,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼髓绽!你這毒婦竟也來了敛苇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎枫攀,沒想到半個月后括饶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡来涨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年图焰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹦掐。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡技羔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出卧抗,到底是詐尸還是另有隱情藤滥,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布社裆,位于F島的核電站拙绊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏泳秀。R本人自食惡果不足惜标沪,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嗜傅。 院中可真熱鬧金句,春花似錦、人聲如沸吕嘀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽币他。三九已至坞靶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蝴悉,已是汗流浹背彰阴。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拍冠,地道東北人尿这。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像庆杜,于是被迫代替她去往敵國和親射众。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容