首页 > 其他分享 >聊聊 PerformanceObserver

聊聊 PerformanceObserver

时间:2022-10-20 15:44:44浏览次数:78  
标签:const observer PerformanceObserver paint 聊聊 entry 页面

 背景

在用户体验越来越重要的今天,关注页面性能、提升页面展现速度及交互体验逐渐成为前端开发非常重要的事情。

为了监测页面性能,chrome 开发团队就提出过监测网页性能的一些指标,比如 FP、FCP等,还有我们公司自己的北斗网站的秒开率、快开比等。但是这些指标具体怎样获取呢,今天我们就来仔细了解下这个性能监控有关的 API:PerformanceObserver。

一、历史

说起 PerformanceObserver,我们首先要了解下 Performance Timeline。

Performance Timeline 是 W3C 性能小组提出的一个规范,定义了让开发者在应用整个生命周期内收集各类性能指标的接口。

一般情况下,我们想得到某项性能记录,需要知道指定的性能事件已经发生,比如使用定时轮询的方式,主动调用 performance.getEntries 或者 performance.getEntriesByName 来获取。

为了解决这个问题,在 Performance Timeline Level 2 中,除了扩展了 Performance 的基本定义之外,还增加了 PerformanceObserver 接口,于是最新的 Performance Timeline Level 2 标准中包括了如下三点:

  • 扩展了 Performance 接口的基本定义

  • 在 Web Workers 中暴露了 PerformanceEntry

  • 增加了 PerformanceObserver 的支持

此时我们本篇文章的主角:PerformanceObserver 带着它自身的使命终于出现了。

二、介绍 PerformanceObserver

了解了 PerformanceObserver 出现的背景,接下来我们就重点了解下它的具体用法吧。

1、简介

PerformanceObserver 主要用于监测性能度量事件,在浏览器的性能时间轴记录新的 performanceEntry(详见下方介绍) 时会被通知。

通过使用 PerformanceObserver() 构造函数我们可以创建并返回一个新的 PerformanceObserver 对象,从而进行性能的监测。

也就是说,性能指标可以通过 window.performance 获取,但是获取什么时候的指标就可以通过 PerformanceObserver 构造函数生成的实例,在不同的时机拿到对应不同的值。

2、PerformanceEntry

a. 首先我们先看下 mdn 中对它的介绍:

 

 意思大概是,在页面运行过程中我们可以通过 PerformanceEntry 实例持续获取性能数据,拿到粒度更细的流程的 performance 数据信息,也称为 performance metric。而 PerformanceEntry 可以通过 performance.getEntries() 获取到,打印一下大概如下:

  可以看出打印出来的是一个数组,而数组中的每一项都是 PerformanceEntry 的实例。PerformanceEntry 可以理解为描述浏览器中某一个行为的性能指标,比如获取资源文件的性能,一次事件的性能,渲染页面的性能等等。

b. PerformanceEntry 实例

说起 PerformanceEntry 数组中的实例,主要包括这么几个:

PerformanceResourceTiming:该实例主要用于确定页面各个资源加载所花费的时间,比如获取css、js、img文件、http接口等资源请求花费的时间。通过看 entryType 字段可以看到对应的 entryType 是 resource。

 

PerformanceNavigationTiming:这个实例用于确定一个页面从开始加载到结束需要的时间。通过看 entryType 字段可以看到对应的 entryType 是 navigation。

PerformancePaintTiming:这个实例主要是获取页面刷新渲染过程中,第一个像素点呈现在页面上的时间(first paint),以及第一个 dom 元素呈现在页面上的时间(first contentful paint)。通过看 entryType 字段可以看到对应的 entryType 是 paint。

 

c. entryType

通过下方表格可以看出,entryType 主要有 6 种类型,分别对应 6 个 sybtype,其中就包含了上方我们列出的部分实例。

 

 

 

了解了 PerformanceEntry,接下来我们了解下 PerformanceObserver 具体有哪些方法。

3、方法

PerformanceObserver 主要有3个方法。

a. PerformanceObserver.observe():当传参中的性能指标在上方指定的 entryTypes 之中时,该性能指标的回调函数将会被调用并返回。

b. PerformanceObserver.disconnect():停止性能观察者回调接收到性能指标。

c. PerformanceObserver.takeRecords():返回存储在性能观察器中的性能指标的列表,并将其清空。

4、示例

接下来,我们就重点用 PerformanceObserver 的 observe() 这个方法,分别简单实现下性能优化方面比较常见的几个性能指标数据吧。

a. FP(first-paint),从页面加载开始到第一个像素绘制到屏幕上的时间,也可以把 FP 理解成白屏时间。

const entryHandler = (list) => {        
    for (const entry of list.getEntries()) {
        if (entry.name === 'first-paint') {
            observer.disconnect()
        }

       console.log(entry)
    }
}

const observer = new PerformanceObserver(entryHandler)
observer.observe({ type: 'paint', buffered: true })
 

通过以上代码可以得到 FP 的内容:

其中 startTime 就是我们要的绘制时间。

b. FCP(first-contentful-paint),从页面加载开始到所有页面内容在屏幕上完成渲染的时间。

const entryHandler = (list) => {        
    for (const entry of list.getEntries()) {
        if (entry.name === 'first-contentful-paint') {
            observer.disconnect()
        }

        console.log(entry)
    }
}

const observer = new PerformanceObserver(entryHandler)
observer.observe({ type: 'paint', buffered: true })
 通过以上代码可以得到 FCP 的内容:

其中 startTime 就是我们要的绘制时间。

c. LCP(largest-contentful-paint),从页面加载开始到最大文本块或图像元素在屏幕上完成渲染的时间。LCP 指标会根据页面首次开始加载的时间点来报告可视区域内可见的最大图像或文本块完成渲染的相对时间。

const entryHandler = (list) => {
    if (observer) {
        observer.disconnect()
    }

    for (const entry of list.getEntries()) {
        console.log(entry)
    }
}

const observer = new PerformanceObserver(entryHandler)
observer.observe({ type: 'largest-contentful-paint', buffered: true })

通过以上代码可以得到 LCP 的内容:

其中 startTime 就是我们要的绘制时间。element 是指 LCP 绘制的 DOM 元素。

通过监测用户访问页面的这些性能数据,可以直观的看到在哪些方面我们需要进行性能提升,从而可以根据不同页面的展现情况针对性的提高用户体验。

5、兼容性

了解了 PerformanceObserver 的具体做法,紧接着我们看下它目前的兼容性吧。

从表中我们可以看出,PerformanceObserver 的兼容性其实已经覆盖大部分浏览器了。对于比如 IE 或者移动端部分不兼容的浏览器,可以考虑使用我们下方介绍的观察者 Observer 中的 MutationObserver 进行代替。

而 MutationObserver 又是什么呢,接下来我们再简单介绍下。

6、MutationObserver

MutationObserver 在监听的 DOM 元素属性发生变化时会触发事件,与 PerformanceObserver 相同,也是一个观察者 API。

接下来我们通过 MutationObserver 简单实现下获取 FCP 首屏渲染时间。

const next = window.requestAnimationFrame ? requestAnimationFrame : setTimeout
const ignoreDOMList = ['STYLE', 'SCRIPT', 'LINK']

observer = new MutationObserver(mutationList => {
    const entry = {
        children: [],
    }

    for (const mutation of mutationList) {
        if (mutation.addedNodes.length && isInScreen(mutation.target)) {
             // ...
        }
    }

    if (entry.children.length) {
        entries.push(entry)
        next(() => {
            entry.startTime = performance.now()
        })
    }
})

observer.observe(document, {
    childList: true,
    subtree: true,
})

具体思路大致如下

(1)利用 MutationObserver 监听 document 对象,每当 DOM 元素属性发生变更时,触发事件。

(2)判断该 DOM 元素是否在首屏内,如果在,则在 requestAnimationFrame() 回调函数中调用 performance.now() 获取当前时间,作为它的绘制时间。

(3)将最后一个 DOM 元素的绘制时间和首屏中所有加载的图片时间作对比,将最大值作为首屏渲染时间。

这样就通过 MutationObserver 简单获取了首屏时间。

 

 

总结

至此,我们的 PerformanceObserver 就基本介绍完成了。PerformanceObserver 这个 API 涉及的内容挺多,本篇文章就针对以下几个内容简单介绍了下:

1、平时我们页面的性能指标数据可以通过 window.performance 获取,但是获取的时机就可以通过 PerformanceObserver 进行监测获取到对应指标。

2、我们可以通过 PerformanceEntry 实例持续获取性能数据,拿到粒度更细的流程的 performance 数据信息。

3、使用 PerformanceObserver 提供的方法 observe() 方法简单实现了 FP、FCP、LCP 指标数据的获取。

4、最后我们简单实现了通过 MutationObserver 获取 FCP 数据。

 

参考链接

现代浏览器观察者 Observer API 指南

https://developer.mozilla.org/zh-CN/docs/Web/API/Performance_Timeline

https://developer.mozilla.org/zh-CN/docs/Web/API/PerformanceObserver

https://developer.mozilla.org/zh-CN/docs/Web/API/PerformanceEntry/entryType

https://developer.mozilla.org/zh-CN/docs/Web/API/PerformanceNavigationTiming

https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver

Google网站核心指标Core web vitals(LCP、FID、CLS)是什么

标签:const,observer,PerformanceObserver,paint,聊聊,entry,页面
From: https://www.cnblogs.com/momo798/p/16810097.html

相关文章

  • 聊聊工作和职业规划
    此篇随笔,非技术性内容,都是自己关于工作、学习以及职业规划里的一些思考和迷茫的地方吧,一直计划着写出来,但总被一些琐事烦扰,凡人都有的困扰啊。。。 about工作作为一个......
  • 聊聊运营活动的设计与实现逻辑
    产品留不住,唯有套路得用户;一、业务背景在多数的产品功能体系中,都会设计活动板块,活动作为运营的手段,根本目的是为了更好的连接产品和用户,所以很考验运营方案的策划,在活......
  • CSS自定义字体 竖向偏移怎么办?聊聊字体文件的字体度量、上升、下降
    背景昨天我发布了联机象棋《联机象棋发布!打开URL就能联机对战!观战!单机演练!分享残局!》,有玩家试玩,截图如下:通过截图大小以及里面的emoji我推断出:这是一台WindowsPC。之前我在......
  • 聊聊yolact
    Yolact系列文章很多YolactYolact++Yolactedge  https://arxiv.org/pdf/2012.12259.pdf  yolact的结构总体长的没有什么特别的,如果就看featurebackbone+feature......
  • 聊聊技术写作的个人体会
     有群友问过,是什么原因使我开始写技术公众号,又是什么动力让我坚持写的。在我看来,写作是一件不能敷衍的事,通过写作来学习,反而要比单纯地学习的效果要好。为了写成一篇“拿得......
  • leetcode必备算法:聊聊滑动窗口
    前言我们刷leetcode的时候,经常会遇到滑动窗口类型题目。滑动窗口问题非常经典,也很有技巧性,一般大厂也喜欢问。今天跟大家一起来学习滑动窗口的套路,文章如果有不正确的地方,......
  • #yyds干货盘点#今天聊聊JS的Function
    Object.prototype是原型的创造者,任何原型都源自它;而Function.prototype是仅次于Object.prototype的存在,它是内置构造函数的创建者,任何构造函数都源自它。​Function(构......
  • #yyds干货盘点#今天聊聊大文件上传
    文件上传在开发中的需求比较多,上传的解决方案也很多,咱们下面一一来看:文件上传普通表单上传使用PHP来展示常规的表单上传是一个不错的选择。首先构建文件上传的表单,并指定表......
  • 聊聊Vuex原理
    背景Vuex是一个专为Vue.js应用程序开发的状态管理模式。Vuex是专门为Vue.js设计的状态管理库,以利用Vue.js的细粒度数据响应机制来进行高效的状态更新。如果你已......
  • Microsoft 365 解决方案:聊聊SharePoint List View Threshold 那些事
    51CTO博客链接:​​​https://blog.51cto.com/u_13637423​​ 最近一段时间,给客户或者Partner处理问题时,经常面临SharePoint列表视图阈值问题,今天整理本文给大家介绍一下......