摘要:前言最近有幸參與一個前端質(zhì)量監(jiān)控類項目的重構(gòu),算是個人初次接觸到前端質(zhì)量監(jiān)控相關(guān)的知識,對于其中的性能統(tǒng)計部分很感興趣,查詢資料之后寫了文章,作為個人學(xué)習(xí)記錄,如有錯誤,敬請斧正頁面整體性能通過瀏覽器提供的方法,我們能夠得到網(wǎng)頁每個處理階段
前言
最近有幸參與一個前端質(zhì)量監(jiān)控類項目的重構(gòu),算是個人初次接觸到前端質(zhì)量監(jiān)控相關(guān)的知識,對于其中的性能統(tǒng)計部分很感興趣,查詢資料之后寫了文章,作為個人學(xué)習(xí)記錄,如有錯誤,敬請斧正
1.頁面整體性能通過瀏覽器提供的 window.performance.timing 方法,我們能夠得到網(wǎng)頁每個處理階段的精確時間。打開一個頁面后,這些信息會被瀏覽器記錄下來,我們直接在控制臺輸出,就可以查看結(jié)果
該對象下有多個字段,每個字段都對應(yīng)著瀏覽器加載一個頁面的某個階段,下面這張圖詳細(xì)的展示了瀏覽器加載一個頁面的詳細(xì)過程
https://segmentfault.com/img/...
window.performance = { timing: { // 同一個域下,前一個網(wǎng) unload 的時間戳, // 如果直接復(fù)制地址進(jìn)入或者不是同域 // 則與 fetchStart 值相等 navigationStart: 1441112691935, // 前一個網(wǎng)頁unload 的時間戳, // 如果無前一個網(wǎng)頁 unload // 或者前一個網(wǎng)頁與當(dāng)前頁面不同域,則值為 0 unloadEventStart: 0, // 和 unloadEventStart 相對應(yīng) // 返回前一個網(wǎng)頁 unload 事件綁定的回調(diào)函數(shù)執(zhí)行完畢的時間戳 unloadEventEnd: 0, // 第一個 HTTP 重定向發(fā)生時的時間。 // 有跳轉(zhuǎn)且是同域名內(nèi)的重定向才算 // 否則值為 0 redirectStart: 0, // 最后一個 HTTP 重定向完成時的時間 // 有跳轉(zhuǎn)且是同域名內(nèi)部的重定向才算 // 否則值為 0 redirectEnd: 0, // 瀏覽器準(zhǔn)備好使用 HTTP 請求抓取文檔的時間 // 發(fā)生在檢查本地緩存之前 fetchStart: 1441112692155, // DNS 域名查詢開始的時間 // 如果使用了本地緩存(即無 DNS 查詢)或持久連接 // 則與 fetchStart 值相等 domainLookupStart: 1441112692155, // DNS 域名查詢完成的時間 // 如果使用了本地緩存(即無 DNS 查詢)或持久連接 // 則與 fetchStart 值相等 domainLookupEnd: 1441112692155, // HTTP(TCP) 開始建立連接的時間 // 如果是持久連接,則與 fetchStart 值相等 // 注意如果在傳輸層發(fā)生了錯誤且重新建立連接, // 則顯示的是新建立的連接開始的時間 connectStart: 1441112692155, // HTTP(TCP) 完成建立連接的時間(完成握手) // 如果是持久連接,則與 fetchStart 值相等 // 注意如果在傳輸層發(fā)生了錯誤且重新建立連接, // 則顯示的是新建立的連接完成的時間 // 注意這里握手結(jié)束,包括安全連接建立完成、SOCKS 授權(quán)通過 connectEnd: 1441112692155, // HTTPS 連接開始的時間, // 如果不是安全連接,則值為 0 secureConnectionStart: 0, // HTTP 請求讀取真實文檔開始的時間(完成建立連接 // 包括從本地讀取緩存 // 連接錯誤重連時,這里顯示的也是新建立連接的時間 requestStart: 1441112692158, // HTTP 開始接收響應(yīng)的時間(獲取到第一個字節(jié)) // 包括從本地讀取緩存 responseStart: 1441112692686, // HTTP 響應(yīng)全部接收完成的時間(獲取到最后一個字節(jié)) // 包括從本地讀取緩存 responseEnd: 1441112692687, // 開始解析渲染 DOM 樹的時間 // 此時 Document.readyState 變?yōu)?loading // 并將拋出 readystatechange 相關(guān)事件 domLoading: 1441112692690, // 完成解析 DOM 樹的時間 // Document.readyState 變?yōu)?interactive // 并將拋出 readystatechange 相關(guān)事件 // 注意只是 DOM 樹解析完成 // 此時并沒有開始加載網(wǎng)頁內(nèi)的資源 domInteractive: 1441112693093, // DOM 解析完成后,網(wǎng)頁內(nèi)資源加載開始的時間 // 在 DOMContentLoaded 事件拋出前發(fā)生 domContentLoadedEventStart: 1441112693093, // DOM 解析完成后, // 網(wǎng)頁內(nèi)資源加載完成的時間 // 如 JS 腳本加載執(zhí)行完 domContentLoadedEventEnd: 1441112693101, // DOM 樹解析完成 // 且資源也準(zhǔn)備就緒的時間 // Document.readyState 變?yōu)?complete // 此時拋出 readystatechange 相關(guān)事件 domComplete: 1441112693214, // load 事件發(fā)送給文檔 // 也即 load 回調(diào)函數(shù)開始執(zhí)行的時間 // 注意如果沒有綁定 load 事件,值為 0 loadEventStart: 1441112693214, // load 事件的回調(diào)函數(shù)執(zhí)行完畢的時間 loadEventEnd: 1441112693215 } }
通過這些值,我們就能得到某個階段具體的時間差,進(jìn)行一些簡單的計算, 就能夠得到網(wǎng)頁的各項性能數(shù)據(jù),便于我們在某個階段做優(yōu)化
// DOM解析時間 var domParseTime = domComplete - responseEnd; // DNS解析時間 var domainLookUpTime = domainLookupEnd - domainLookupStart;2. 頁面中各個資源的性能
上面我們用 window.performance.timing 方法得到的是整個頁面的耗時,在一些情況下,我們想要知道頁面上某個靜態(tài)資源的加載時間,那么我們就可以用三個方法來獲取這些信息
window.performance.getEntries // 返回網(wǎng)頁中所有資源和標(biāo)記的數(shù)據(jù)
window.performance.getEntriesByType // 根據(jù)entryType返回數(shù)據(jù)
window.performance.getEntriesByName // 根據(jù)name返回數(shù)據(jù)
其中 window.performance.getEntries 可以獲取到所有資源信息和所有標(biāo)記信息(何為標(biāo)記信息,我們后面會講到), 而我們想看的只是 entryType: "resource" 這些資源的信息,所以我們可以直接使用 window.performance.getEntriesByType("resource") 方法來獲得我們的信息,該方法會返回一個數(shù)組,包含字段如下
var entries = [{ // 資源的絕對路徑 name: "http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js", // 資源類型 entryType: "resource", // css: 通過css請求的資源。類型不定 // img: 圖片 // link: 通過link標(biāo)簽請求的資源: css/favicon // script: js文件 // xmlhttprequest: 一般為GET方式的數(shù)據(jù)接口 initiatorType: "script", // 加載時間 duration: 18.13399999809917, // 這些字段的意義同上面 // 不同之處只表示這一個資源的時間 redirectStart: 0, redirectEnd: 0, fetchStart: 233.346999992829828, domainLookupStart: 0, domainLookupEnd: 0, connectStart: 0, connectEnd: 0, secureConnectionStart: 0, requestStart: 0, responseStart: 0, responseEnd: 442.7109999960521, startTime: 424.57699999795295 }];
這些數(shù)據(jù)里面,initiatorType的值需要注意下, initiatorType 并不是指資源的類型,而是指 請求該資源的請求類型, 如上圖所示 initiatorType: "css" 的時候,資源文件并不是一個css文件,而是一張 img圖片,表明該圖片是通過css去請求到的(通常是設(shè)置背景圖),而直接在網(wǎng)頁中通過 或在代碼中通過 new Image 請求的圖片,initiatorType 值都為 img,我們以下面這段代碼為例
通過CSS加載的圖片
通過 img 標(biāo)簽直接加載
通過 new Image() 加載的圖片
打開頁面之后在控制臺輸出結(jié)果, 也驗證了結(jié)果
另外值得注意的一個點是,除了這三張圖片,我們在頁面中還加載了2個css文件和1個js文件,分別是
index.css // 本地文件
bootstrap.min.css // 遠(yuǎn)程
jquery.min.js // 遠(yuǎn)程
仔細(xì)觀察的話,會發(fā)現(xiàn)這幾個文件有一些不同之處,我們對數(shù)據(jù)稍作處理,方便參看
我們會發(fā)現(xiàn),其中的 bootstrap.min.css 的很多字段數(shù)據(jù)都為0,查詢資料之后才知道,該方法通常情況下只能獲得本域名下資源的加載信息(所以 index.css 的信息直接就能獲取到)
如果想要獲取遠(yuǎn)程資源的加載信息的只有在response里面顯式的設(shè)置 Timing-Allow-Origin:* 類似于(Acces-Control-Allow-Origin的設(shè)置)
我們直接打開了 jquery.min.js 連接, 看到了 Timing-Allow-Origin 字段,所以我們能夠獲得該資源的準(zhǔn)確信息, 而在 bootstrap.min.css 的返回中,我們沒有找到 Timing-Allow-Origin 字段, 所以數(shù)據(jù)都顯示為0
3. 代碼執(zhí)行計時通常情況下,我們想要取得一段代碼的執(zhí)行時間,會做以下操作
var start = +new Date(); for (var i = 0; i < 100; i++) { ret.push(i); } var end = +new Date(); console.log("執(zhí)行時間", end - start);
但不足之處在于, new Date 的精確度只到秒, 而有時候我們的代碼執(zhí)行在1s之內(nèi),計算出的差值為0,此時就顯得無能為力。所以,我們可能通過如下兩種方式,解決這個問題
1. 通過 window.performance.nowvar start = window.performance.now(); for (var i = 0; i < 100; i++) { ret.push(i); } var end = window.performance.now(); console.log("執(zhí)行時間", end - start);
使用方式十分簡單,該方法能夠計算出精確到 百萬分之一秒 的時間差。與 new Date 不同之處在于 window.performance.now 方法返回的是相對于 performance.timing.navigationStart 即頁面初始化的時間,但我們的關(guān)注點是差值, 所以時間從哪兒算起,對于我們來說并不重要
2. 使用 window.performance.mark 和 window.performance.measure// 標(biāo)記開始 window.performance.mark("start"); for (var i = 0; i < 100; i++) { ret.push(i); } // 標(biāo)記結(jié)束 window.performance.mark("end"); // 計算差值并命名為difference, 無返回 window.performance.measure("difference", "start", "end");
通過 window.performance.mark 方法,我們在指定地方打上一個記號,此時不會返回任何值,會被記錄到performance 對象里, entryType 被默認(rèn)標(biāo)記為了 mark。
然后通過 window.performance.measure 計算出差值,并通過第一個參數(shù)對其賦名為 difference, 此時也沒有返回值,這些值也被記錄到了 performance 對象里,它們的 entryType 被默認(rèn)標(biāo)記為了 measure.
所以我們可以通過兩種方式來查看差值
window.performance.getEntriesByType("measure")
`window.perform
esByName("difference")`
![圖片上傳中...]
在使用完了之后,我們還可以對這些標(biāo)識,進(jìn)行統(tǒng)一的清理
// 清除指定標(biāo)記點 window.performance.clearMarks("start"); // 清除所有標(biāo)記點 window.performance.clearMarks(); // 清除指定差值數(shù)據(jù) window.performance.clearMeasures("difference"); // 清除所有差值數(shù)據(jù) window.performance.clearMeasures();
通過這兩種方式,都可以精確的計算出十分精確的時間差值,那如何做選擇呢? 我的建議是,如果只是單純的想要得到少數(shù)的差值,直接在代碼中使用 now, 而如果需要統(tǒng)計大量的值, 就應(yīng)該使用 mark 和 measure 方法,因為這些值都會存在 performance 對象里,我們可以在任意需要的時候,通過讀取數(shù)組,十分便捷的對數(shù)據(jù)做統(tǒng)一處理與管理
API支持 && 參考瀏覽器對Performance支持情況
http://www.infoq.com/cn/articles/html5-performance-api-monitoring
http://ju.outofmemory.cn/entry/204774
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/99107.html
摘要:端優(yōu)談?wù)勱P(guān)于前端的緩存的問題我們都知道對頁面進(jìn)行緩存能夠有利于減少請求發(fā)送,從而達(dá)到對頁面的優(yōu)化。而作為一名有追求的前端,勢必要力所能及地優(yōu)化我們前端頁面的性能。這種方式主要解決了淺談前端中的過早優(yōu)化問題過早優(yōu)化是萬惡之源。 優(yōu)化向:單頁應(yīng)用多路由預(yù)渲染指南 Ajax 技術(shù)的出現(xiàn),讓我們的 Web 應(yīng)用能夠在不刷新的狀態(tài)下顯示不同頁面的內(nèi)容,這就是單頁應(yīng)用。在一個單頁應(yīng)用中,往往只有一...
摘要:基本入門前端掘金作者本文屬于翻譯文章,原文鏈接為。如果如何把應(yīng)用放在容器中運(yùn)行掘金本文適合零基礎(chǔ),且希望使用運(yùn)行應(yīng)用的人士。后端掘金使用構(gòu)建網(wǎng)站。 nginx 基本入門 - 前端 - 掘金作者:villainthr 本文屬于翻譯文章,原文鏈接為 nginx Beginner’s Guide。是至今為止見過最好的 nginx 入門文章。額。。。沒有之一。 這篇教程簡單介紹了 nginx ...
摘要:前言月份開始出沒社區(qū),現(xiàn)在差不多月了,按照工作的說法,就是差不多過了三個月的試用期,準(zhǔn)備轉(zhuǎn)正了一般來說,差不多到了轉(zhuǎn)正的時候,會進(jìn)行總結(jié)或者分享會議那么今天我就把看過的一些學(xué)習(xí)資源主要是博客,博文推薦分享給大家。 1.前言 6月份開始出沒社區(qū),現(xiàn)在差不多9月了,按照工作的說法,就是差不多過了三個月的試用期,準(zhǔn)備轉(zhuǎn)正了!一般來說,差不多到了轉(zhuǎn)正的時候,會進(jìn)行總結(jié)或者分享會議!那么今天我就...
閱讀 937·2023-04-26 01:34
閱讀 3371·2023-04-25 20:58
閱讀 3324·2021-11-08 13:22
閱讀 2126·2019-08-30 14:17
閱讀 2537·2019-08-29 15:27
閱讀 2687·2019-08-29 12:45
閱讀 3011·2019-08-29 12:26
閱讀 2824·2019-08-28 17:51