1. 程式人生 > 其它 >js檢測頁面效能指標

js檢測頁面效能指標

檢測獲取fp、fcp、lcp、cls效能指標:

window.monitor = {
  isWinLoad: false,
  observer: null,
  sessionValue: 0,
  sessionEntries: [],
  data: {
    fp: 0,
    fcp: 0,
    lcp: 0,
    cls: 0
  }
}
/**
PerformanceObserver類進行監聽
 */
window.monitor.observer = new PerformanceObserver(function (list) {
  for (const entry of list.getEntries()) {
    // lcp獲得
    if (entry.entryType === 'largest-contentful-paint') {
      window.monitor.data.lcp = entry.startTime
    }
    // cls計算
    if (entry.entryType === 'layout-shift') {
      // 只計算沒有最近使用者輸入的佈局移位。
      if (!entry.hadRecentInput) {
        const firstSessionEntry = window.monitor.sessionEntries[0]
        const lastSessionEntry = window.monitor.sessionEntries[window.monitor.sessionEntries.length - 1]

        // 如果該條目發生在前一個條目之後不到1秒,且在會話中的第一個條目之後不到5秒,則將該條目包含在當前會話中。否則,開始一個新的會話。
        if (
          window.monitor.sessionValue &&
              entry.startTime - lastSessionEntry.startTime < 1000 &&
              entry.startTime - firstSessionEntry.startTime < 5000
        ) {
          window.monitor.sessionValue += entry.value
          window.monitor.sessionEntries.push(entry)
        } else {
          window.monitor.sessionValue = entry.value
          window.monitor.sessionEntries = [entry]
        }
        // 如果當前會話值大於當前CLS值,則更新CLS及其表項。
        if (window.monitor.sessionValue > window.monitor.data.cls) {
          window.monitor.data.cls = window.monitor.sessionValue
        }
      }
    }
    // fp、fcp獲得
    if (entry.entryType === 'paint') {
      if (entry.name === 'first-paint') {
        window.monitor.data.fp = entry.startTime
      }
      if (entry.name === 'first-contentful-paint') {
        window.monitor.data.fcp = entry.startTime
      }
    }
  }
})

/**
entryTypes還有其他型別,這裡只監聽三個型別
buffered 屬性表示是否觀察快取資料,也就是說觀察程式碼新增時機比事情觸發時機晚也沒關係。
 */
window.monitor.observer.observe(
  {
    entryTypes: ['paint', 'largest-contentful-paint', 'layout-shift'],
    buffered: true
  }
)

window.addEventListener('load', function () {
  window.monitor.isWinLoad = true
}, true)

window.addEventListener('beforeunload', function () {
  if (window.monitor.isWinLoad) {
    console.log(window.monitor)
    /**
beforeunload應該選擇什麼樣的方式進行傳輸上報?
非同步ajax是不可靠的,無非保證上報。

可選擇方式有以下幾種:

1、同步ajax
同步ajax會阻斷瀏覽器的unload,直到ajax環節結束後才會繼續進行unload。
此方法的缺點是由於頁面會在ajax請求結束後才延遲解除安裝,會導致關閉時瀏覽器出現卡頓降低使用者的體驗。
注意:chrome不支援在頁面關閉事件內使用同步XMLHttpRequest請求

2、beacon
beacon api設計就是用來解決頁面解除安裝時傳送請求的問題。他能保證在頁面unload完成前請求能夠被髮送,並且由於其是非同步且非阻塞的,並不會影響瀏覽器其他頁面的顯示效率。
sendBeacon只能傳送http post請求。
問題:此方法無法自定義header資訊,如果服務端設定了token許可權攔截,sendBeacon並沒有辦法將token資訊放入請求中。

3、fetch
fetch方法配合引數中的keepalive欄位會讓瀏覽器在頁面解除安裝後在後臺繼續接管網路請求,該欄位是必須的。
此方法的缺陷為keepalive欄位一次只能承載最大64KB的請求內容,且該限制是所有並行請求共享的,即,頁面解除安裝階段所有fetch+keepalive請求的內容體總和不能超過64KB。

4、建立img攜帶資訊
此方法是get請求方式將引數傳遞,get引數本身可攜帶資訊有限,不可傳遞大量資訊。

     */
  }
}, true)

  

其他效能指標日後更新,參考連結https://zhuanlan.zhihu.com/p/420330110