好好学习,认真工作

页面性能计算

计算 LargestContentPaint

 1 function observeLargestConentPaint(){
 2   if (!utils.canIUse('PerformanceObserver')) return;
 3   new PerformanceObserver((entryList) => {
 4     for (const entry of entryList.getEntries()) {
 5       const largestConentPaint = entry.startTime
 6       setPageInfo(pageId, {
 7         largestConentPaint
 8       })
 9     }
10   }).observe({ type: 'largest-contentful-paint', buffered: true });
11 }

 

计算首屏渲染时间

监听首屏dom渲染时机

 1 /**
 2  * 计算首屏渲染时间
 3  */
 4 entries = [];
 5 function observeFirstScreen(params) {
 6   if (!utils.canIUse('MutationObserver')) return;
 7   const next = window.requestAnimationFrame ? requestAnimationFrame : setTimeout
 8   const ignoreDOMList = ['STYLE', 'SCRIPT', 'LINK']
 9   const viewportWidth = window.innerWidth
10   const viewportHeight = window.innerHeight
11   // dom 对象是否在屏幕内
12   function isInScreen(dom) {
13     const rectInfo = dom.getBoundingClientRect()
14     if (rectInfo.left < viewportWidth && rectInfo.top < viewportHeight) {
15       return true
16     }
17 
18     return false
19   }
20   const observer = new MutationObserver(mutationList => {
21     const next = window.requestAnimationFrame ? requestAnimationFrame : setTimeout
22     const entry = {
23       children: [],
24     }
25     for (const mutation of mutationList) {
26       if (mutation.addedNodes.length && isInScreen(mutation.target)) {
27         console.log(mutation)
28         entry.children.push(mutation.target)
29         // ...
30       }
31     }
32 
33     if (entry.children.length) {
34       entries.push(entry)
35       next(() => {
36         entry.startTime = performance.now()
37       })
38     }
39   })
40 
41   observer.observe(document, {
42     childList: true,
43     subtree: true,
44   })
45 }
46 function getRenderTime() {
47   let startTime = 0
48   entries.forEach(entry => {
49     if (entry.startTime > startTime) {
50       startTime = entry.startTime
51     }
52   })
53 
54   // 需要和当前页面所有加载图片的时间做对比,取最大值
55   // 图片请求时间要小于 startTime,响应结束时间要大于 startTime
56   // performance.getEntriesByType('resource').forEach(item => {
57   //   if (
58   //     item.initiatorType === 'img'
59   //     && item.fetchStart < startTime
60   //     && item.responseEnd > startTime
61   //   ) {
62   //     startTime = item.responseEnd
63   //   }
64   // })
65 
66   return startTime
67 }

 

上报时机

第一点,必须要在 DOM 不再变化后再上报渲染时间,一般 load 事件触发后,DOM 就不再变化了。所以我们可以在这个时间点进行上报。

第二点,可以在 LCP 事件触发后再进行上报。不管是同步还是异步加载的 DOM,它都需要进行绘制,所以可以监听 LCP 事件,在该事件触发后才允许进行上报。

 1 let isOnLoaded = false
 2 executeAfterLoad(() => {
 3     isOnLoaded = true
 4 })
 5 
 6 
 7 let timer
 8 let observer
 9 function checkDOMChange() {
10     clearTimeout(timer)
11     timer = setTimeout(() => {
12         // 等 load、lcp 事件触发后并且 DOM 树不再变化时,计算首屏渲染时间
13         if (isOnLoaded && isLCPDone()) {
14             observer && observer.disconnect()
15             lazyReportCache({
16                 type: 'performance',
17                 subType: 'first-screen-paint',
18                 startTime: getRenderTime(),
19                 pageURL: getPageURL(),
20             })
21 
22             entries = null
23         } else {
24             checkDOMChange()
25         }
26     }, 500)
27 }

 

 

 
posted on 2024-05-30 16:07  peace_1  阅读(3)  评论(0编辑  收藏  举报