前端性能监控指标

简介: 前端性能指标包括白屏时间、首屏时间、DOM可操作时间和页面总加载时间。可通过注入代码或`window.performance` API进行量化统计,后者基于浏览器标准接口,提供精确的网络、解析与渲染各阶段耗时数据,助力性能优化。
  1. 前端性能统计的指标有哪些?
  2. 白屏时间:从打开网站到有内容渲染出来的时间节点;
  3. 首屏时间:首屏内容渲染完毕的时间节点;
  4. 用户可操作时间节点:domready触发节点;
  5. 总下载时间:window.onload的触发节点。
  6. 如何统计前端的性能(量化统计)?
    下面介绍几种以上几个数据的统计方案。
    2.1 常规统计方案
    使用注入代码监控的方式统计以上指标,在没有一些浏览器新API(如下文将提到的timing API)的支持下,得到的数据大都是估值,虽然不准确,但也有一定的参考价值。
    2.1.1 白屏时间
    白屏时间节点指的是从用户进入网站(输入url、刷新、跳转等方式)的时刻开始计算,一直到页面有内容展示出来的时间节点。这个过程包括dns查询、建立tcp连接、发送首个http请求(如果使用https还要介入TLS的验证时间)、返回html文档、html文档head解析完毕。
    使用注入代码监控无法获取解析html文档之前的时间信息,目前普遍使用的白屏时间统计方案是在html文档的head中所有的静态资源以及内嵌脚本/样式之前记录一个时间点,在head最底部记录另一个时间点,两者的差值作为白屏时间。如下:










上述代码中的end_time和start_time的差值一般作为白屏时间的估值,但理论上来讲,这个差值只是浏览器解析html文档head的时间,并非准确的白屏时间。
2.1.2 首屏时间
首屏时间的统计比较复杂,目前应用比较广的方案是将首屏的图片、iframe等资源添加onload事件,获取最慢的一个。
这种方案比较适合首屏元素数量固定的页面,比如移动端首屏不论屏幕大小都展示相同数量的内容,响应式得改变内容的字体、尺寸等。但是对于首屏元素不固定的页面,这种方案并不适用,最典型的就是PC端页面,不同屏幕尺寸下展示的首屏内容不同。上述方案便不适用于此场景。
2.1.3 可操作时间
用户可操作的时间节点即dom ready触发的时间,使用jquery可以通过$(document).ready()获取此数据,如果不使用jQuery可以参考这里通过原生方法实现dom ready。
2.1.4 总下载时间
Note
总下载时间即window.onload触发的时间节点。
目前大多数web产品都有异步加载的内容,比如图片的lazyload等。如果总下载时间需要统计到这些数据,可以借鉴AOP的理念,在请求异步内容之前和之后分别打点,最后计算差值。不过通常来讲,我们说的总下载时间并不包括异步加载的内容。
2.2 使用window.performance API
Note
window.performance 是W3C性能小组引入的新的API,目前IE9以上的浏览器都支持。
一个performance对象的完整结构包括:
  • memory字段代表JavaScript对内存的占用。
  • navigation字段统计的是一些网页导航相关的数据:
  • redirectCount:重定向的数量(只读),但是这个接口有同源策略限制,即仅能检测同源的重定向;
  • type 返回值应该是0,1,2 中的一个。分别对应三个枚举值:
    ○ 0 : TYPE_NAVIGATE (用户通过常规导航方式访问页面,比如点一个链接,或者一般的get方式)
    ○ 1 : TYPE_RELOAD (用户通过刷新,包括JS调用刷新接口等方式访问页面)
    ○ 2 : TYPE_BACK_FORWARD (用户通过后退按钮访问本页面) 最重要的是timing字段的统计数据,它包含了网络、解析等一系列的时间数据。
    2.2.1 timing API
    timing的整体结构包括:

  • startTime:有些浏览器实现为navigationStart,代表浏览器开始unload前一个页面文档的开始时间节点。比如我们当前正在浏览baidu.com,在地址栏输入google.com并回车,浏览器的执行动作依次为:unload当前文档(即baidu.com)->请求下一文档(即google.com)。navigationStart的值便是触发unload当前文档的时间节点。
    ○ 如果当前文档为空,则navigationStart的值等于fetchStart。

  • redirectStart和redirectEnd:如果页面是由redirect而来,则redirectStart和redirectEnd分别代表redirect开始和结束的时间节点;
  • unloadEventStart和unloadEventEnd:如果前一个文档和请求的文档是同一个域的,则unloadEventStart和unloadEventEnd分别代表浏览器unload前一个文档的开始和结束时间节点。否则两者都等于0;
  • fetchStart是指在浏览器发起任何请求之前的时间值。在fetchStart和domainLookupStart之间,浏览器会检查当前文档的缓存;
  • domainLookupStart和domainLookupEnd分别代表DNS查询的开始和结束时间节点。如果浏览器没有进行DNS查询(比如使用了cache),则两者的值都等于fetchStart;
  • connectStart和connectEnd分别代表TCP建立连接和连接成功的时间节点。如果浏览器没有进行TCP连接(比如使用持久化连接webscoket),则两者都等于domainLookupEnd;
  • secureConnectionStart:可选。如果页面使用HTTPS,它的值是安全连接握手之前的时刻。如果该属性不可用,则返回undefined。如果该属性可用,但没有使用HTTPS,则返回0;
  • requestStart代表浏览器发起请求的时间节点,请求的方式可以是请求服务器、缓存、本地资源等;
  • responseStart和responseEnd分别代表浏览器收到从服务器端(或缓存、本地资源)响应回的第一个字节和最后一个字节数据的时刻;
  • domLoading代表浏览器开始解析html文档的时间节点。我们知道IE浏览器下的document有readyState属性,domLoading的值就等于readyState改变为loading的时间节点;
  • domInteractive代表浏览器解析html文档的状态为interactive时的时间节点。domInteractive并非DOMReady,它早于DOMReady触发,代表html文档解析完毕(即dom tree创建完成)但是内嵌资源(比如外链css、js等)还未加载的时间点;
  • domContentLoadedEventStart:代表DOMContentLoaded事件触发的时间节点:
  • 页面文档完全加载并解析完毕之后,会触发DOMContentLoaded事件,HTML文档不会等待样式文件,图片文件,子框架页面的加载(load事件可以用来检测HTML页面是否完全加载完毕(fully-loaded))。
  • domContentLoadedEventEnd:代表DOMContentLoaded事件完成的时间节点,此刻用户可以对页面进行操作,也就是jQuery中的domready时间;
  • domComplete:html文档完全解析完毕的时间节点;
  • loadEventStart和loadEventEnd分别代表onload事件触发和结束的时间节点
    2.2.2 计算性能指标
    Note
    可以使用Navigation.timing 统计到的时间数据来计算一些页面性能指标,比如DNS查询耗时、白屏时间、domready等等。
    ● DNS查询耗时 = domainLookupEnd - domainLookupStart
    ● TCP链接耗时 = connectEnd - connectStart
    ● request请求耗时 = responseEnd - responseStart
    ● 解析dom树耗时 = domComplete - domInteractive
    ● 白屏时间 = domloadng - fetchStart
    ● domready时间 = domContentLoadedEventEnd - fetchStart
    ● onload时间 = loadEventEnd - fetchStart
    2.2.3 统计代码
    ```js // 计算加载时间 function getPerformanceTiming () { var performance = window.performance;
    if (!performance) {
    // 当前浏览器不支持
    console.log('你的浏览器不支持 performance 接口');
    return;
    }
  • var t = performance.timing;
    var times = {};

    //【重要】页面加载完成的时间
    //【原因】这几乎代表了用户等待页面可用的时间
    times.loadPage = t.loadEventEnd - t.navigationStart;

    //【重要】解析 DOM 树结构的时间
    //【原因】反省下你的 DOM 树嵌套是不是太多了!
    times.domReady = t.domComplete - t.responseEnd;

    //【重要】重定向的时间
    //【原因】拒绝重定向!比如,http://example.com/ 就不该写成 http://example.com
    times.redirect = t.redirectEnd - t.redirectStart;

    //【重要】DNS 查询时间
    //【原因】DNS 预加载做了么?页面内是不是使用了太多不同的域名导致域名查询的时间太长?
    // 可使用 HTML5 Prefetch 预查询 DNS ,见:HTML5 prefetch
    times.lookupDomain = t.domainLookupEnd - t.domainLookupStart;

    //【重要】读取页面第一个字节的时间
    //【原因】这可以理解为用户拿到你的资源占用的时间,加异地机房了么,加CDN 处理了么?加带宽了么?加 CPU 运算速度了么?
    // TTFB 即 Time To First Byte 的意思
    // 维基百科:https://en.wikipedia.org/wiki/Time_To_First_Byte
    times.ttfb = t.responseStart - t.navigationStart;

    //【重要】内容加载完成的时间
    //【原因】页面内容经过 gzip 压缩了么,静态资源 css/js 等压缩了么?
    times.request = t.responseEnd - t.requestStart;

    //【重要】执行 onload 回调函数的时间
    //【原因】是否太多不必要的操作都放到 onload 回调函数里执行了,考虑过延迟加载、按需加载的策略么?
    times.loadEvent = t.loadEventEnd - t.loadEventStart;

    // DNS 缓存时间
    times.appcache = t.domainLookupStart - t.fetchStart;

    // 卸载页面的时间
    times.unloadEvent = t.unloadEventEnd - t.unloadEventStart;

    // TCP 建立连接完成握手的时间
    times.connect = t.connectEnd - t.connectStart;

    return times;

    相关文章
    |
    Web App开发 缓存 前端开发
    前端性能优化:从入门到精通
    【2月更文挑战第3天】
    452 1
    |
    测试技术
    JMeter压力测试简单例子
    JMeter压力测试简单例子
    708 0
    |
    6月前
    |
    JavaScript 前端开发 UED
    告别卡顿:用虚拟滚动征服超长列表
    告别卡顿:用虚拟滚动征服超长列表
    448 112
    |
    9月前
    |
    边缘计算 监控 前端开发
    《前端性能监控深解:从指标捕获到数据洞察的完整脉络》
    本文深入剖析前端性能监控的完整脉络,从其对用户体验与业务增长的关键价值切入,解读加载、交互、视觉稳定性等核心性能指标,阐述利用原生API、开源库及自定义埋点的指标采集策略,探讨数据上报传输优化与分析洞察方法,还涉及实践中的兼容性、数据准确性等挑战及未来发展趋势,为理解前端性能监控提供全面且深入的视角。
    220 0
    |
    数据采集 监控 数据管理
    【能力比对】数据质量管理VS数据质量平台
    杭州奥零数据科技有限公司成立于2023年,专注于数据中台业务,维护开源项目AllData并提供商业版解决方案。AllData提供数据集成、存储、开发、治理及BI展示等一站式服务,支持AI大模型应用,助力企业高效利用数据价值。
    【能力比对】数据质量管理VS数据质量平台
    |
    缓存 前端开发 JavaScript
    微前端集成优化:让所有子应用体积更小,加载更快!
    【8月更文挑战第17天】微前端集成优化:让所有子应用体积更小,加载更快!
    591 1
    微前端集成优化:让所有子应用体积更小,加载更快!
    |
    移动开发 JavaScript 前端开发
    使用css 与 js 两种方式实现导航栏吸顶效果
    使用css 与 js 两种方式实现导航栏吸顶效果
    |
    JavaScript 算法 前端开发
    【VUE】Vue的diff算法和React的diff算法
    【VUE】Vue的diff算法和React的diff算法
    |
    SQL 缓存 运维
    使用篇丨链路追踪(Tracing)很简单:链路拓扑
    使用篇丨链路追踪(Tracing)很简单:链路拓扑
    32143 108
    |
    JavaScript 前端开发 安全
    TypeScript 常用高级类型
    TypeScript 常用高级类型
    834 0