js如何實現(xiàn)性能監(jiān)控 前端性能監(jiān)控的5個關(guān)鍵指標(biāo)

前端性能監(jiān)控通過埋點、數(shù)據(jù)采集、分析和可視化發(fā)現(xiàn)性能瓶頸并提供改進方向。其5個關(guān)鍵指標(biāo)為:首屏加載時間、白屏?xí)r間、首次可交互時間(tti)、頁面總加載時間和資源加載錯誤率。1. 首屏加載時間可在

中記錄起始時間,在domcontentloaded事件后計算差值;2. 白屏?xí)r間通過mutationobserver監(jiān)聽dom變化并計算起始與首次渲染的時間差;3. tti可通過performancelongtasktiming與事件監(jiān)聽結(jié)合判斷頁面是否完全可交互;4. 頁面總加載時間通過window.onload或performance api獲取完整加載耗時;5. 資源加載錯誤率通過監(jiān)聽onerror事件統(tǒng)計資源加載失敗比例。性能數(shù)據(jù)可通過fetch或xmlhttprequest發(fā)送至監(jiān)控系統(tǒng),以實現(xiàn)持續(xù)優(yōu)化用戶體驗。

js如何實現(xiàn)性能監(jiān)控 前端性能監(jiān)控的5個關(guān)鍵指標(biāo)

前端性能監(jiān)控對于優(yōu)化用戶體驗至關(guān)重要。它就像一個隱形的醫(yī)生,默默守護著你的網(wǎng)站或應(yīng)用,確保它運行流暢、響應(yīng)迅速。

js如何實現(xiàn)性能監(jiān)控 前端性能監(jiān)控的5個關(guān)鍵指標(biāo)

前端性能監(jiān)控主要通過埋點、數(shù)據(jù)采集、分析和可視化來發(fā)現(xiàn)性能瓶頸,并提供改進方向。

js如何實現(xiàn)性能監(jiān)控 前端性能監(jiān)控的5個關(guān)鍵指標(biāo)

前端性能監(jiān)控的5個關(guān)鍵指標(biāo)

立即學(xué)習(xí)前端免費學(xué)習(xí)筆記(深入)”;

  • 首屏加載時間: 用戶第一眼看到頁面的時間。
  • 白屏?xí)r間: 從用戶訪問到頁面開始顯示內(nèi)容的時間。
  • 首次可交互時間 (TTI): 頁面變得完全可交互的時間。
  • 頁面總加載時間: 加載所有資源所需的時間。
  • 資源加載錯誤率: 頁面資源加載失敗的比例。

如何使用 JavaScript 監(jiān)控首屏加載時間?

首屏加載時間是用戶體驗的黃金指標(biāo)。你可以通過以下步驟使用 JavaScript 監(jiān)控它:

js如何實現(xiàn)性能監(jiān)控 前端性能監(jiān)控的5個關(guān)鍵指標(biāo)

  1. 在 中添加時間戳:html 的 部分,盡可能靠前的位置,添加一個內(nèi)聯(lián)的 JavaScript 腳本,記錄頁面開始加載的時間。
<head>   <script>     window.performanceStartTime = new Date().getTime();   </script>   ... </head>
  1. 在首屏內(nèi)容加載完成后計算時間差: 在首屏內(nèi)容加載完成后,通常是在 DOMContentLoaded 事件觸發(fā)后,或者在首屏圖片加載完成后,計算當(dāng)前時間與 performanceStartTime 的差值。
document.addEventListener('DOMContentLoaded', function() {   setTimeout(function() { // 延遲一段時間,確保首屏內(nèi)容渲染完成     const now = new Date().getTime();     const firstScreenTime = now - window.performanceStartTime;     console.log('首屏加載時間:', firstScreenTime + 'ms');     // 將數(shù)據(jù)發(fā)送到你的監(jiān)控系統(tǒng)     sendPerformanceData({ firstScreenTime: firstScreenTime });   }, 500); // 延遲 500ms,根據(jù)實際情況調(diào)整 });  function sendPerformanceData(data) {   // 使用 fetch 或 XMLHttpRequest 發(fā)送數(shù)據(jù)   fetch('/api/performance', {     method: 'POST',     headers: {       'Content-Type': 'application/JSon'     },     body: JSON.stringify(data)   }).then(response => {     // 處理響應(yīng)   }).catch(error => {     console.error('發(fā)送性能數(shù)據(jù)失敗:', error);   }); }
  1. 考慮使用 Performance API: 更精確的方式是使用 Performance API,它可以提供更詳細(xì)的性能數(shù)據(jù),例如 DNS 查詢時間、TCP 連接時間、請求響應(yīng)時間等。
window.onload = function() {   setTimeout(function() {     const performance = window.performance;     if (!performance) {       console.log('Performance API 不可用');       return;     }      const timing = performance.timing;     const firstPaint = timing.domContentLoadedEventEnd - timing.navigationStart;     console.log('首屏渲染時間 (domContentLoadedEventEnd - navigationStart):', firstPaint + 'ms');      // 發(fā)送性能數(shù)據(jù)     sendPerformanceData({ firstPaint: firstPaint });   }, 500); };

注意事項:

  • 延遲:setTimeout 的延遲時間需要根據(jù)實際情況調(diào)整,確保首屏內(nèi)容已經(jīng)渲染完成。
  • 準(zhǔn)確性:首屏的定義可能因應(yīng)用而異,需要根據(jù)實際情況選擇合適的時機計算時間差。
  • 數(shù)據(jù)發(fā)送:sendPerformanceData 函數(shù)需要根據(jù)你的監(jiān)控系統(tǒng)進行調(diào)整。

如何監(jiān)控白屏?xí)r間?

白屏?xí)r間是指用戶打開頁面到看到任何內(nèi)容的時間間隔。優(yōu)化白屏?xí)r間能顯著改善用戶體驗。

  1. 埋點: 在 標(biāo)簽中,緊跟在 之前插入一個內(nèi)聯(lián) JavaScript 腳本,記錄頁面開始渲染的時間戳。
<head>   <script>     window.pageStartTime = new Date().getTime();   </script> </head>
  1. 計算白屏?xí)r間: 在頁面首次渲染內(nèi)容出現(xiàn)后(例如,在首個 DOM 元素渲染后),立即計算當(dāng)前時間與 pageStartTime 的差值。可以使用 MutationObserver 監(jiān)聽 DOM 變化。
const observer = new MutationObserver(function(mutations) {   if (document.body) { // 檢查 body 是否存在,防止過早觸發(fā)     const now = new Date().getTime();     const blankScreenTime = now - window.pageStartTime;     console.log('白屏?xí)r間:', blankScreenTime + 'ms');     sendPerformanceData({ blankScreenTime: blankScreenTime });     observer.disconnect(); // 停止監(jiān)聽   } });  observer.observe(document.documentElement, {   childList: true,   subtree: true });
  1. 數(shù)據(jù)上報: 將計算得到的白屏?xí)r間發(fā)送到你的監(jiān)控系統(tǒng)。

關(guān)鍵點:

  • MutationObserver:用于監(jiān)聽 DOM 變化,一旦檢測到頁面開始渲染,立即計算白屏?xí)r間。
  • observer.disconnect():停止監(jiān)聽,避免重復(fù)計算。
  • 確保在 標(biāo)簽存在后才開始監(jiān)聽,避免在 body 標(biāo)簽還未加載時就觸發(fā)。

首次可交互時間 (TTI) 如何準(zhǔn)確測量?

TTI 是指頁面變得完全可交互的時間,例如用戶可以點擊按鈕、填寫表單等。準(zhǔn)確測量 TTI 比較復(fù)雜,因為它涉及到判斷頁面上的所有關(guān)鍵元素是否都已加載并可響應(yīng)用戶輸入。

  1. 使用 Performance API 的 PerformanceLongTaskTiming: 監(jiān)聽長時間任務(wù)(Long Tasks),這些任務(wù)會阻塞線程,影響頁面的交互性。
const observer = new PerformanceObserver((list) => {   list.getEntries().forEach((entry) => {     console.log('Long Task:', entry.duration, entry.name, entry.startTime);     // 可以將 Long Task 的信息發(fā)送到監(jiān)控系統(tǒng),用于分析 TTI   }); });  observer.observe({ type: 'longtask', buffered: true });
  1. 結(jié)合事件監(jiān)聽: 監(jiān)聽關(guān)鍵元素的事件,例如按鈕的 click 事件、輸入框的 input 事件等,判斷這些元素是否能夠響應(yīng)用戶輸入。
const interactiveElements = document.querySelectorAll('button, input, select, textarea'); let ttiDetected = false;  interactiveElements.forEach(element => {   element.addEventListener('click', function() {     if (!ttiDetected) {       ttiDetected = true;       const now = new Date().getTime();       console.log('TTI:', now + 'ms');       sendPerformanceData({ tti: now });     }   }); });
  1. 使用 Lighthouse 等工具 Lighthouse 可以自動測量 TTI,并提供詳細(xì)的性能分析報告。

挑戰(zhàn):

  • TTI 的定義比較模糊,需要根據(jù)實際應(yīng)用場景進行調(diào)整。
  • 準(zhǔn)確判斷頁面是否完全可交互比較困難,需要綜合考慮多種因素。

如何監(jiān)控頁面總加載時間和資源加載錯誤率?

頁面總加載時間是指加載所有資源所需的時間。資源加載錯誤率是指頁面資源加載失敗的比例。

  1. 頁面總加載時間: 使用 window.onload 事件或 Performance API 測量頁面總加載時間。
window.onload = function() {   const performance = window.performance;   const timing = performance.timing;   const pageLoadTime = timing.loadEventEnd - timing.navigationStart;   console.log('頁面總加載時間:', pageLoadTime + 'ms');   sendPerformanceData({ pageLoadTime: pageLoadTime }); };
  1. 資源加載錯誤率: 監(jiān)聽 window.onerror 事件和 img.onerror 等事件,記錄資源加載失敗的次數(shù)。
let errorCount = 0; window.onerror = function(message, source, lineno, colno, error) {   console.error('資源加載錯誤:', message, source, lineno, colno, error);   errorCount++; };  const images = document.querySelectorAll('img'); images.forEach(img => {   img.onerror = function() {     console.error('圖片加載失敗:', img.src);     errorCount++;   }; });  window.addEventListener('load', function() {   const totalResources = document.querySelectorAll('link[rel="stylesheet"], script, img').length;   const errorRate = errorCount / totalResources;   console.log('資源加載錯誤率:', errorRate);   sendPerformanceData({ errorRate: errorRate }); });

注意事項:

  • 需要統(tǒng)計所有類型的資源加載錯誤,例如 css、JavaScript、圖片等。
  • 資源加載錯誤率應(yīng)該盡可能低,否則會嚴(yán)重影響用戶體驗。

如何將性能數(shù)據(jù)發(fā)送到監(jiān)控系統(tǒng)?

將性能數(shù)據(jù)發(fā)送到監(jiān)控系統(tǒng)是性能監(jiān)控的關(guān)鍵一步。可以使用 fetch 或 XMLHttpRequest 發(fā)送數(shù)據(jù)。

function sendPerformanceData(data) {   fetch('/api/performance', {     method: 'POST',     headers: {       'Content-Type': 'application/json'     },     body: JSON.stringify(data)   }).then(response => {     if (!response.ok) {       console.error('發(fā)送性能數(shù)據(jù)失敗:', response.status);     }   }).catch(error => {     console.error('發(fā)送性能數(shù)據(jù)失敗:', error);   }); }

關(guān)鍵點:

  • 選擇合適的 API 端點:/api/performance 只是一個示例,需要根據(jù)你的監(jiān)控系統(tǒng)進行調(diào)整。
  • 處理錯誤:需要處理數(shù)據(jù)發(fā)送失敗的情況,例如網(wǎng)絡(luò)錯誤、服務(wù)器錯誤等。
  • 數(shù)據(jù)格式:確保數(shù)據(jù)格式與監(jiān)控系統(tǒng)兼容。

通過上述方法,你可以使用 JavaScript 實現(xiàn)前端性能監(jiān)控,并收集關(guān)鍵指標(biāo),從而優(yōu)化你的網(wǎng)站或應(yīng)用,提升用戶體驗。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊11 分享