2

谷歌浏览器内嵌了性能测试工具Lighthouse,F12打开能看到,使用参考: Lighthouse工具

前端性能监控,设置监控超时的任务,回传到服务器

完整代码如下

// 在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 事件后,采用异步加载的方式:

// 在项目的入口文件的底部,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)
  }
}

万年打野易大师
1.5k 声望1.1k 粉丝