性能监控指标| 8月更文挑战

495 阅读5分钟

性能是前端领域始终绕不开的话题,因为性能影响用户的使用体感如何、留存率等多个方面,是衡量一个产品的重要指标之一,重要性无需赘言,那么我们该如何量化衡量性能的好坏呢?

衡量一个产品的性能有非常多的工具和指标,那么我们该掌握哪些性能指标?接下来就让我们一起看看

性能指标

接下来就让我们一起看看常见的业界较为公认的一些性能指标

  • 首次绘制(FP)和首次有内容绘制(FCP)时间
  • 首次有意义绘制(FMP)时间
  • 大量有意义绘制(LCP)时间
  • 首屏时间
  • 用户可交互(TTI)时间
  • 总下载时间

接下来分别看看每个指标的含义。

首次绘制(FP)时间:对于应用页面,用户在视觉上首次出现不同于跳转之前的内容时间点,或者说是页面发生第一次绘制的时间点。

首次有内容绘制(FCP)时间:指浏览器完成渲染 DOM 中第一个内容的时间点,可能是文本、图像或者其他任何元素,此时用户应该在视觉上有直观的感受。

首次有意义绘制(FMP)时间:指页面关键元素渲染时间。这个概念并没有标准化定义,因为关键元素可以由开发者自行定义——究竟什么是“有意义”的内容,只有开发者或者产品经理自己了解。

大量有意义绘制(LCP)时间:用于衡量标准报告视口内可见的最大内容元素的渲染时间。为了提供良好的用户体验,网站应努力在开始加载页面的前 2.5 秒内进行 最大内容渲染

首屏时间:对于所有网页应用,这是一个非常重要的指标。用大白话来说,就是进入页面之后,应用渲染完整个手机屏幕(未滚动之前)内容的时间。需要注意的是,业界对于这个指标其实同样并没有确切的定论,比如这个时间是否包含手机屏幕内图片的渲染完成时间。 

用户可交互时间:顾名思义,也就是用户可以与应用进行交互的时间。一般来讲,我们认为是 domready 的时间,因为我们通常会在这时候绑定事件操作。如果页面中涉及交互的脚本没有下载完成,那么当然没有到达所谓的用户可交互时间

总下载时间:页面所有资源加载完成所需要的时间。一般可以统计 window.onload 时间,这样可以统计出同步加载的资源全部加载完的耗时。如果页面中存在较多异步渲染,也可以将异步渲染全部完成的时间作为总下载时间。

可以通过浏览器的performance进行查看这些指标

image-20210731131340493.png

通过图中可以看到有一个DCL(DOMContentLoaded的指标,我们需要注意其与Load 事件的区别:其实从这两个事件的命名我们就能体会,DOMContentLoaded 指的是文档中 DOM 内容加载完毕的时间,也就是说 HTML 结构已经完整。但是我们知道,很多页面包含图片、特殊字体、视频、音频等其他资源,这些资源由网络请求获取,DOM 内容加载完毕时,由于这些资源往往需要额外的网络请求,还没有请求或者渲染完成。而当页面上所有资源加载完成后,load 事件才会被触发。因此,在时间线上,load 事件往往会落后于 DOMContentLoaded 事件。

获取性能数据

了解上述这些指标之后,接下来让我们看一下这些指标是如何计算获取

目前最为流行和靠谱的方案是采用 Performance API,它非常强大:不仅包含了页面性能的相关数据,还带有页面资源加载和异步请求的相关数据。

关于performance解析:

const window.performance = { 
    memory: {
        usedJSHeapSize,
        totalJSHeapSize,
        jsHeapSizeLimit
    },

    navigation: {
        // 页面重定向跳转到当前页面的次数
        redirectCount,
        // 以哪种方式进入页面
        // 0 正常跳转进入
        // 1 window.location.reload() 重新刷新
        // 2 通过浏览器历史记录,以及前进后退进入
        // 255 其他方式进入
        type,         
    },

    timing: {
        // 等于前一个页面 unload 时间,如果没有前一个页面,则等于 fetchStart 时间
        navigationStart
        // 前一个页面 unload 时间,如果没有前一个页面或者前一个页面与当前页面不同域,则值为 0
        unloadEventStart,
        // 前一个页面 unload 事件绑定的回调函数执行完毕的时间
        unloadEventEnd,
        redirectStart,
        redirectEnd,
        // 检查缓存前,准备请求第一个资源的时间
        fetchStart,
        // 域名查询开始的时间
        domainLookupStart,
        // 域名查询结束的时间
        domainLookupEnd,
        // HTTP(TCP) 开始建立连接的时间            connectStart,
        // HTTP(TCP)建立连接结束的时间
        connectEnd,
        secureConnectionStart,
        // 连接建立完成后,请求文档开始的时间
        requestStart,
        // 连接建立完成后,文档开始返回并收到内容的时间
        responseStart,
        // 最后一个字节返回并收到内容的时间
        responseEnd,
        // Document.readyState 值为 loading 的时间
        domLoading,
        // Document.readyState 值为 interactive
        domInteractive,
        // DOMContentLoaded 事件开始时间
        domContentLoadedEventStart,
        // DOMContentLoaded 事件结束时间
        domContentLoadedEventEnd,
        // Document.readyState 值为 complete 的时间            domComplete,
        // load 事件开始的时间
        loadEventStart,
        // load 事件结束的时间
        loadEventEnd
    }
}

根据这些事件节点,通过做差便可以计算出一下典型的指标

let times = {}
let t = window.performance.timing

// 解析 DOM 树耗时
times.analysisTime = t.domComplete - t.domInteractive

// 白屏时间
times.blankTime = t.domLoading - t.fetchStart

// 用户可交互时间
times.domReadyTime = t.domContentLoadedEventEnd - t.fetchStart

// 用户等待页面完全可用的时间
times.loadPage = t.loadEventEnd - t.navigationStart