性能分析
主要分析4个方面fcp(衡量白屏时间)、TTI(页面可用性,开始到主要子资源完成渲染,用户最早可交互时间)、LCP(主要内容在可视区域变得可见时间)、CLS(累积布局偏移。量化了在页面加载期间,视口中元素的移动程度)
获取示例
js
export const perfor = () => {
console.log('start************************************')
// const observer = new PerformanceObserver(function (list) {
// const perfEntries = list.getEntries()
// for (const perfEntry of perfEntries) {
// console.log(perfEntry.name, perfEntry.startTime)
// }
// })
// observer.observe({ entryTypes: [ 'paint' ] })
const longtask: any = []
let FCP = 0
let sessionEntries: any = []
let sessionValue = 0
const metric: any = {
value: 0
}
const per = new PerformanceObserver((entryList: any) => {
for (const entry of entryList.getEntries()) {
/* cls */
if (!entry.hadRecentInput) {
const firstSessionEntry = sessionEntries[0]
const lastSessionEntry = sessionEntries[sessionEntries.length - 1]
if (sessionValue && entry.startTime - lastSessionEntry.startTime < 1000 && entry.startTime - firstSessionEntry.startTime < 5000) {
// 如果时间靠近上一个 session, 将本轮 layout-shift 累加进上一个 session
sessionValue += entry.value
sessionEntries.push(entry)
} else {
// 新起一个 session
sessionValue = entry.value
sessionEntries = [ entry ]
}
// 如果当前 session 的 value 大于之前的最大值,替换为现在这个大的
if (sessionValue > metric.value) {
metric.value = sessionValue
metric.entries = sessionEntries
/* 页面稳定性。累积布局偏移。量化了在页面加载期间,视口中元素的移动程度。CLS 推荐值为低于 0.1,越低说明页面跳来跳去的情况就越少,用户体验越好。页面评分占比25% */
console.log('CLS: ', metric)
}
}
if (entry.entryType === 'largest-contentful-paint') {
/* 大内容,主要内容在可视区域变得可见时间点,以交互前最近一次报告为准 页面评分占比42% */
console.log(entry.entryType + ':LCP', entry.startTime, (entry as any).element)
}
if (entry.entryType === 'navigation') {
const Load = entry.loadEventStart - entry.fetchStart
const DOMContentLoaded = entry.domContentLoadedEventStart - entry.fetchStart
console.log('DOM加载完成', DOMContentLoaded)
console.log('页面及资源全部加载完成', Load)
}
if (entry.entryType === 'longtask') {
longtask.push(entry)
}
if (entry.entryType === 'first-input') {
const firstInputDelay = entry.processingStart - entry.startTime
/* 测量实际能够开始处理事件处理程序所经过的时间,即交互延迟时间 0 - 100 100 - 300 */
console.log('firstInput-Delay: FID', firstInputDelay)
console.log('firstInput-Duration', entry.duration)
console.log('firstInput-Target', entry.target)
if (!longtask.length) return
const lastLongTask = longtask.slice(-1)[0]
/* FCP 之后最长的长任务耗时, 没长任务就是负数 */
console.log('MPFID', lastLongTask.startTime - entry.startTime)
}
}
})
window.onload = () => {
setTimeout(() => {
const timing = window.performance.timing
// console.log(timing)
/* timing1 */
const { redirectStart, redirectEnd, fetchStart, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart,
responseStart, responseEnd , domLoading, domComplete, navigationStart, loadEventEnd, domContentLoadedEventStart, domInteractive
} = timing
console.log('old start**************************************')
console.log('重定向 Redirect', redirectEnd - redirectStart)
console.log('缓存 App cache', domainLookupStart - fetchStart)
console.log('DNS 解析', domainLookupEnd - domainLookupStart)
console.log('TCP建连', connectEnd - connectStart)
console.log('SSL 握手', connectEnd - secureConnectionStart)
console.log('请求耗时', responseStart - requestStart)
console.log('响应耗时', responseEnd - responseStart)
console.log('Processing', domComplete - domLoading)
console.log('DOMReady', domContentLoadedEventStart - fetchStart)
console.log('页面完全加载耗时', loadEventEnd - navigationStart)
console.log('dom 解析耗时', domInteractive - responseEnd)
console.log('页面请求到收到应答 TTFB', responseStart - navigationStart)
console.log('剩余资源加载耗时', domComplete - domContentLoadedEventStart)
console.log('old end**************************************')
/* 新监听 */
newPerformance()
// new PerformanceObserver((list: any) => {
// for (const entry of list.getEntries()) {
// const Load = entry.loadEventStart - entry.fetchStart
// const DOMContentLoaded = entry.domContentLoadedEventStart - entry.fetchStart
// console.log('DOM加载完成', DOMContentLoaded)
// console.log('页面及资源全部加载完成', Load)
// }
// }).observe({ type: 'navigation', buffered: true })
/* fp fcp */
const paint = window.performance.getEntriesByType('paint')
for (const perfEntry of paint) {
/* FP 白屏时间,0 - 1000 1000 - 2500 */
/* FCP 衡量首屏时间 0 - 1800 1800 - 3000 页面评分占比16% */
console.log(perfEntry.name, perfEntry.startTime, perfEntry)
if (perfEntry.name === 'first-contentful-paint') {
FCP = perfEntry.startTime + perfEntry.duration
}
}
/* TTI TBT */
setTimeout(() => {
if (!longtask.length) return
const { startTime, duration } = longtask.slice(-1)[0]
/* 页面可用性,开始到主要子资源完成渲染,越小,代表用户可以更能早操作页面 0 - 3800 good 3800 - 7300 needs pro 页面评分占比17% */
console.log('TTI', startTime + duration)
/* 页面开始渲染到可以操作页面的时间 */
console.log('TBT', startTime + duration - FCP)
}, 4000)
}, 1000)
/* LCP */
per.observe({ type: 'largest-contentful-paint', buffered: true })
/* dom load */
per.observe({ type: 'navigation', buffered: true })
per.observe({ type: 'longtask', buffered: true })
per.observe({ type: 'first-input', buffered: true })
/* cls */
per.observe({ type: 'layout-shift',buffered: true })
}
}
function newPerformance () {
console.log(performance.getEntriesByType('navigation')[0])
console.log("new start**************************************")
const { redirectEnd, redirectStart, domainLookupEnd, domainLookupStart, fetchStart, connectEnd, connectStart,
secureConnectionStart, responseStart, responseEnd, requestStart, domComplete, domContentLoadedEventStart, loadEventEnd,
duration, domInteractive, navigationStart
} = performance.getEntriesByType('navigation')[0] as any
console.log('重定向 Redirect', redirectEnd - redirectStart)
console.log('缓存 App cache', domainLookupStart - fetchStart)
console.log('DNS 解析', domainLookupEnd - domainLookupStart)
console.log('TCP建连', connectEnd - connectStart)
console.log('SSL 握手', connectEnd - secureConnectionStart)
console.log('请求耗时', responseStart - requestStart)
console.log('响应耗时', responseEnd - responseEnd)
console.log('Processing', domComplete)
console.log('DOMReady', domContentLoadedEventStart - fetchStart)
console.log('页面完全加载耗时', loadEventEnd - responseEnd, duration)
console.log('dom 解析耗时', domInteractive)
console.log('页面请求到收到应答 TTFB', responseStart)
console.log('剩余资源加载耗时', domComplete - domContentLoadedEventStart)
console.log("new old**************************************")
}https://jonny-wei.github.io/blog/devops/performance/indicator.html
JStar