封裝一個performance監控類

前端性能監控,設置監控超時的任務,回傳到服務器前端

完整代碼以下ios

// 在src/utils/PerformanceMonitor.js
export default class PerformanceMonitor {
    constructor() {
        // 設置基礎毫秒
        this.SEC = 1000
        // 設置超時時差
        this.TIMEOUT = 10 * this.SEC
        // 基礎配置,上傳數據
        this.config = {}
    }
    init(option) {
        // 向前兼容
        if (!window.performance) return false
        const { url, timeoutUrl, method = 'POST', timeout = 10000 } = option
        this.config = {
            url,
            timeoutUrl,
            method,
            timeout
        }
    }
    // 上報兩項核心數據
    logPackage() {
        const { url, timeoutUrl, method } = this.config
        const domComplete = this.getLoadTime()
        const timeoutRes = this.getTimeoutRes(this.config.timeout)
        // 上報頁面加載時間
        this.log(url, { domeComplete }, method)
        // 上報超時加載的資源列表
        if (timeoutRes.length) {
            this.log(timeoutUrl, { timeoutRes }, method)
        }
    }
    // 上報數據
    log(url, data = {}, type = 'POST') {
        const method = type.toLowerCase()
        const urlToUse = method === 'get' ? `${url}?${this.makeItStr(data)}` : url
        const body = method === 'get' ? {} : { body: this.convert2FormData(data) }
        // 接口,可用本身項目封裝的axios
        const init = {
            method,
            ...body
        }
        // 請求接口上報服務器
        fetch(urlToUse, init).catch(e => console.log(e))
    }
    getTimeoutRes(limit = this.TIMEOUT) {
        const isTimeout = this.setTime(limit)
        // 獲取資源加載時間
        const resourceTimes = performance.getEntriesByType('resource')
        // 生成超時資源列表
        return resourceTimes.filter(item => isTimeout(this.getDomLoadTime(item))).map(getName)
    }
    getDomLoadTime() {
        // 獲取頁面加載時間
        const [{ domComplete }] = performance.getEntriesByType('navigation')
        return domComplete
    }
    setTime(limit = this.TIMEOUT) {
        time => time >= limit
    }
    getLoadTime({ startTime, responseEnd }) {
        return responseEnd - startTime
    }
    getName({ name }) {
        return name
    }
    // 生成表單數據
    convert2FormData(data = {}) {
        Object.entries(data).reduce((last, [key, value]) => {
            if (Array.isArray(value)) {
                return value.reduce((lastResult, item) => {
                    lastResult.append(`${key}[]`, item)
                    return lastResult
                }, last)
            }
            last.append(key, value)
            return last
        }, new FormData())
    }

    // 拼接 GET 時的url
    makeItStr(data = {}) {
        Object.entries(data)
            .map(([k, v]) => `${k}=${v}`)
            .join('&')
    }
}

爲了監測工具不佔用主線程的 JavaScript 解析時間。所以,最好在頁面觸發 onload 事件後,採用異步加載的方式:axios

// 在項目的入口文件的底部,js按流程解析
const log = async () => {
  const PM = await import('/src/utils/PerformanceMonitor.js')
  PM.init({ url: 'xxx', timeoutUrl: 'xxxx' })
  PM.logPackage()
}
const oldOnload = window.onload
window.onload = e => { if (oldOnload && typeof oldOnload === 'string') {
    oldOnload(e)
  } // 儘可能不影響頁面主線程
  if (window.requestIdleCallback) {
    window.requestIdleCallback(log)
  } else {
    setTimeout(log)
  }
}
相關文章
相關標籤/搜索