做者:九思
你好,我是九思,來自騰訊前端技術部,擅長前端監控、工程化相關技術。此篇文章將圍繞前端性能優化中監控問題展開討論。css
首先咱們要知道,頁面打開快不快,不是在電腦或手機上的打開速度說了算,也不是測試同窗測試的結果說了算,而是真實用戶使用的時候說了算。前端
那麼如何去監控用戶真實使用時的頁面性能呢?本文將作細緻介紹(建議收藏)bootstrap
頁面上線後,咱們最關心用戶打開頁面的速度,一般就是首屏。跨域
頁面加載離不開靜態資源的加載,包括 js、css、img、video、font 等,在現在盛行 SPA 的場景尤其重要,好比活動頁面會有不少圖片,咱們一般會開發一些模板,由產品/運營同窗來配置,而圖片多大合適是比較難肯定的,網速愈來愈快,你們對清晰度要求也愈來愈高,此時就能夠經過監測這些圖片的加載速度來酌情優化。瀏覽器
數據是頁面中至關重要的元素,能夠說沒有數據,你的頁面幾乎沒有使用價值(純靜態除外)。固然這裏咱們只能粗暴的監控整個請求的總時間,純前端沒法監控各個階段時間,但這對於線上應用也很重要。性能優化
實際上線後,不一樣的應用可能會有不一樣的測速訴求,好比:視頻從加載到播放的時間,此時能夠自定義一些測速點,利用以前講述的打點方式來上報。網絡
這塊其實仍是比較簡單的,只須要利用 PerformanceResourceTiming 便可,而且它的兼容性極高,能夠覆蓋到幾乎全部場景。框架
實際監控時,能夠分兩種場景,若是支持 performanceObserver 能夠實時監聽,不然使用定時器方式,此外須要將此代碼放到頁面最頂層,不然沒法監控到這段代碼以前的資源加載。dom
const typeList = \['script', 'link', 'img'\]; // const staticTime = {}; const dealTime = (entries) => { for (let i = 0, l = entries.length; i < l; i++) { const entry = entries\[i\]; if (typeList.indexOf(entry.initiatorType) !== -1) { staticTime\[entry.name\] = entry.connectEnd - entry.connectStart; } } } if (typeof window.PerformanceObserver === 'function') { const observer = new window.PerformanceObserver((list) => { dealTime(list.getEntries()); }); observer.observe({ entryTypes: \['resource'\] }); } else { setInterval(() => { const allEntries = performance.getEntriesByType('resource'); const entries = allEntries.slice(allEntries.length); dealTime(entries); }, 5000); }
entry 部分數值前端性能
connectEnd: 32.63499999593478
connectStart: 32.63499999593478
decodedBodySize: 160302
domainLookupEnd: 32.63499999593478
domainLookupStart: 32.63499999593478
duration: 37.54000000481028
encodedBodySize: 23876
entryType: "resource"
fetchStart: 32.63499999593478
initiatorType: "link"
name: "https://stackpath.bootstrapcdn.com
nextHopProtocol: "h2"
redirectEnd: 0
redirectStart: 0
requestStart: 44.60999999719206
responseEnd: 70.17500000074506
responseStart: 65.40999999560881
secu reConnectionStart: 32.63499999593478
serverTiming:[]
startTime: 32.63499999593478
transferSize: 23971
workerStart: 0
關於 API 的監控,能夠採用重寫 XHR 或者 fetch,這樣能夠適用任何的框架、請求庫。時間計算則是經過打點的方式,若是隻是固定項目監控,也能夠直接採用打點的方式。若是採用重寫的方式,不只能夠監控請求的時長,還能夠監控請求的成功失敗率。
打點最簡單的方式:
const startTime = Date.now(); fn() // 假設這裏是同步執行 const timeCycle = Date.now() - startTime; // fn的執行耗時
除了以上這幾點,前端監控的實操中咱們還應該考慮到上報、限流以及如何處理這些性能數據。
點擊連接查看詳情:https://ke.sifou.com/course/1...
發送請求咱們很容易想到適用 fetch / XHR,固然也可使用自動發起請求的 HTML 標籤,好比 script、link、img。上報數據雖然能夠拿來分析頁面的真實運行數據,但有一點要注意的是:不能影響當前頁面的運行或最小程度的影響。
是否能夠直接用 fetch/XHR 呢?答案是否認的,由於上報的域名和頁面的域名基本是不一樣的,因此這裏須要能夠前端跨域的方式。
說到跨域,瀏覽器的 src 屬性標籤基本均可以,到底用哪一個呢?原則上要適用對頁面影響最小的那個,諸如 Script、link 這些標籤以前有講述,他們都會對頁面的運行形成影響。
而 img 變成了較爲合適的方式,構造圖片打點不只不用插入DOM,只要在 JS 中 new 出 Image 對象就能發起請求,並且尚未阻塞問題,在沒有js的瀏覽器環境中也能經過 img 標籤正常打點,這是其餘類型的資源請求所作不到的。
在全部圖片中1px x 1px 大小,gif 體積最小,相較 BMP/PNG,能夠節約41%/35%的網絡資源,因此適用 gif 相對是最佳選擇。
頁面的性能數據,每次訪問都會有,若是你的項目 pv 有必定量級,那麼處理起來就會至關耗費資源,並且這些數據咱們最終是求平均值或者分位值,因此不必全量上報。那麼咱們能夠在上報前作一些限流處理。
除了以上這幾點,前端監控的實操中咱們還應該考慮到如何處理這些性能數據,主要有取中位數、平均值、分位數等作法,因爲篇幅有限此處不作詳細介紹。
最後,若是這篇文章給你帶來些許有價值的理解,歡迎點贊、分享,更多內容可翻閱個人付費專欄《前端性能優化12問》。
點擊連接查看詳情:https://ke.sifou.com/course/1...