最近在閱讀 Vue 的源碼的時候去溜達了一圈之前沒有關注過的幾個 API,好比 mark、measure 等等,因而總結一下前端監控利器 performance 相關的知識。前端
可能有些同窗不太瞭解這個 API,由於其實說實話,日常也不會接觸這些,可是這倒是一個頗有用的 API。咱們能夠利用這個 API 完成對頁面的性能表現達到十分精確的度量和控制。git
下面呢,咱們將會一塊兒領略一下 performance 的魅力,關於 performance 的 API 等等的信息,網上其實說的已經很是多了,這裏就再也不贅述,有興趣的能夠自行查閱。github
在 performance 中的 timing 對象裏,存儲了各類與瀏覽器性能有關的時間數據,咱們能夠經過其中的一些屬性來獲取到瀏覽器在不一樣階段處理網頁的耗時統計。web
const { timing } = performance;
const t = {};
// DNS 查詢時間
t.dns = timing.domainLookupEnd - timing.domainLookupStart;
// 解析 DOM 樹時間
t.dom = timing.domComplete - timing.domInteractive;
// 重定向時間
t.redirect = timing.redirectEnd - timing.redirectStart;
// 請求耗時
t.request = timing.responseEnd - timing.requestStart;
// 白屏時間
t.wait = timing.responseStart - timing.navigationStart;
複製代碼
其實咱們能從這些時間裏還可以獲得很是多的信息,上面都是一些很經常使用的時間,咱們能夠從這些信息中獲知整個頁面的總體性能。segmentfault
好比說,當DNS 查詢時間長時,這時候你就要考慮是否是使用的域名太多了,或者有沒有作 DNS 預解析, 關於 DNS 預解析要注意的是在 HTTP 協議下 a 標籤是默認開啓的,而 HTTPS 是默認關閉的,須要本身開啓。數組
當重定向時間長的時候,你就能夠去看看代碼裏這樣的狀況,好比說 https://baidu.com
就會重定向到 https://www.baidu.com
,固然了,重定向的狀況不止這一種,還須要根據自身項目去優化重定向的時間。瀏覽器
當 DOM 解析時間過長的時候,你就要考慮你的 HTML 的結構是否是不合理。咱們能夠經過不一樣的時間去檢測頁面的各類性能,而後針對性的進行修改。微信
先看一段 Vue 的源碼:dom
const perf = inBrowser && window.performance
/* istanbul ignore if */
if (
perf &&
perf.mark &&
perf.measure &&
perf.clearMarks &&
perf.clearMeasures
) {
mark = tag => perf.mark(tag)
measure = (name, startTag, endTag) => {
perf.measure(name, startTag, endTag)
perf.clearMarks(startTag)
perf.clearMarks(endTag)
perf.clearMeasures(name)
}
}
複製代碼
能夠看到,其實它封裝的兩個函數中使用到的就是 performance 中的 mark、measure、clearMarks 以及 clearMeasures 幾個函數。前端性能
performance.mark() 和 performance.clearMarks() 是一組函數,咱們能夠經過使用 performance.mark() 來標記時間戳,咱們能夠經過這些時間戳的名字來計算兩個時間戳中間所花費的時間。
而這樣的計算方式是否是看着有點熟,是的,在 console 裏的 time 和 timeEnd 也可以計時,可是沒有 mark 和 measure 靈活。看下面的例子:
function per() {
performance.mark('per_begin');
for(const a = 1; a < 10000;a++) {}
performance.mark('per_end');
}
per(); // 這時候咱們調用 performance.getEntriesByType('mark') 就能夠看到剛剛咱們標記的兩個時間戳了
// 咱們使用 measure 來計算這兩個標記點之間所消耗的時間
performance.measure('per', 'per_begin', 'per_end'); // 經過 performance.getEntriesByName('per') 就能夠看到 measure 的時間了
複製代碼
Vue 的源碼中對這兩個方法進行了封裝,從實驗中咱們可以看到咱們每次打點以及計算都會在 performance 裏留下記錄,Vue 封裝的方法在計算完成以後將記錄清除掉了。
這裏有些同窗可能就有點困惑了,你 measure 計算的時候計算了就直接 clear 了,這不就白計算了麼?其實,在官方的 devTools 裏使用了 PerformanceObserver 去監聽 performance 的動做,因此監聽到取完值,刪掉也就沒什麼了。
就好比說這樣:
const observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
console.log(`${entry.name}: ${entry.duration}`);
});
});
observer.observe({
entryTypes: ['measure']
});
複製代碼
這樣當咱們調用 performance.measure 就會觸發這個回調函數了。
咱們對前端的監控主要是兩個方面。
第一就是運行錯誤,這個很明顯就是咱們代碼寫得有問題,出現了 bug,咱們能夠在一些能夠預知返回結果的地方主動判斷函數運行是否正確,其次咱們能夠經過 try...catch...
或者是 window.onerror
等方法來進行錯誤的監控。
第二個方面就是對前端加載的資源進行監控,比較經常使用的方法有 Object.onerror 來捕獲錯誤,要注意的是資源的錯誤不會冒泡,就是說 window 是捕獲不到的,那麼還有些什麼其餘辦法呢?固然有,下面說的一種資源監控的方式就要利用到咱們的 performance 了。
順便提一嘴,前端的錯誤咱們能夠經過好比說 Ajax 的方式上報,可是呢?寫 Ajax 仍是比較煩的,你還能夠經過 Image 對象上報錯誤。好了,不扯遠了,咱們繼續看 performance 怎麼監控資源。
咱們隨便打開一個網站,就以掘金爲例,咱們打開瀏覽器控制檯。
// 在控制檯輸入
performance.getEntries();
複製代碼
咱們能夠獲得下面的輸出:
這個 API 返回的是所有加載成功的資源,那麼同時咱們能夠經過 document 去拿到咱們要加載的全部資源。
這時候,咱們就可以經過這兩個數組來看資源的加載狀況了。
performance 這個 API 出來時間也很長了,可是之前一直沒有了解過這個 API,在閱讀源碼的過程當中纔看到,屬於查缺補漏。
關於 performance 的相關資源都在下面,有興趣的能夠看看:
文 / 小烜同窗
本文已由做者受權發佈,版權屬於創宇前端。歡迎註明出處轉載本文。本文連接:knownsec-fed.com/2018-08-09-…
想要看到更多來自知道創宇開發一線的分享,請搜索關注咱們的微信公衆號:創宇前端(KnownsecFED)。歡迎留言討論,咱們會盡量回復。
感謝您的閱讀。