前端性能监控,设置监控超时的工作,回传到服务器
残缺代码如下
// 在 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)
}
}