VUE(nuxt)项目性能监测统计

最近有个需求是监测性能,要求在移动端项目里统计控制台(如下图)最后一行的Finish,DOMContentLoaded和Load三个时间。
在这里插入图片描述

一、指标解释

(1)Finish

  • Finish 时间是页面上所有 http 请求发送到响应完成的时间,HTTP1.0/1.1 协议限定,单个域名的请求并发量是 6 个,即Finish是所有请求(不只是XHR请求,还包括DOC,img,js,css等资源的请求)在并发量为6的限制下完成的时间。

  • 页面发送请求和页面解析文档结构,分属两个不同的线程,所以 Finish 时间与DOMContentLoaded 和 Load 并无直接关系。

  • Finish 的时间比 Load 大,意味着页面有相当部分的请求量,Finish 的时间比 Load 小,意味着页面请求量很少,如果页面是只有一个 html文档请求的静态页面,Finish时间基本就等于HTML文档请求的时间。

(2)DOMContentLoaded

  • 对应页面DOMContentLoaded事件触发的时间点:DOM树构建完成。即HTML页面由上向下解析HTML结构到末尾封闭标签 。

(3)Load

  • 对应页面Load事件触发的时间点:页面加载完毕。 DOM树构建完成后,继续加载html/css 中的图片资源等外部资源,加载完成后视为页面加载完毕。

二、http请求过程及网页渲染原理

(1)http请求过程

在这里插入图片描述

(2)渲染原理

在这里插入图片描述
当我们在浏览器地址输入URL时,浏览器会发送请求到服务器,服务器将请求的HTML文档发送回浏览器,浏览器将文档下载下来后,便开始从上到下解析,解析完成之后,会生成DOM。如果页面中有css,会根据css的内容形成CSSOM,然后DOM和CSSOM会生成一个渲染树,最后浏览器会根据渲染树的内容计算出各个节点在页面中的确切大小和位置,并将其绘制在浏览器上。

html的解析又会被js打断,解析过程中遇到

而在现在浏览器中,为了减缓渲染被阻塞的情况,现代的浏览器都使用了猜测预加载。当解析被阻塞的时候,浏览器会有一个轻量级的HTML(或CSS)扫描器(scanner)继续在文档中扫描,查找那些将来可能能够用到的资源文件的url,在渲染器使用它们之前将其下载下来,并且下载是可以并行进行的,并行的上限一般为6。

三、Performance API

具体参考js标准教程Performance API

主要用到的是performance.timing对象,具体解释见上面的链接,下面这张图对应各个指标的时间点。
在这里插入图片描述

参考这段代码的统计指标

(function  performanceStatistics(){

  var performance = window.performance;

  if (!performance) {
      // 当前浏览器不支持
      console.log('你的浏览器不支持 performance 接口');
      return ;
  }
  var timing = performance.timing;
  // 如果我们需要尽量对页面加载周期的数据进行详细的统计分析:
  console.log('统计模块性能时间:'); // 写出具体模块名称
  console.log('准备新页面时间耗时: ' + (timing.fetchStart - timing.navigationStart) + 'ms');
  console.log('Appcache 耗时: ' + (timing.domainLookupStart - timing.fetchStart)+ 'ms');
  console.log('DNS 查询耗时: ' + (timing.domainLookupEnd - timing.domainLookupStart)+ 'ms');
  console.log('TCP连接耗时: ' + (timing.connectEnd - timing.connectStart)+ 'ms');
  console.log('request请求耗时: ' + (timing.responseEnd - timing.requestStart)+ 'ms');
  console.log('请求完毕至DOM加载: ' + (timing.domInteractive - timing.responseEnd)+ 'ms');
  console.log('解释dom树耗时: ' + ( timing.domComplete - timing.domInteractive)+ 'ms');
  console.log('load事件耗时: ' + ( timing.loadEventEnd - timing.loadEventStart)+ 'ms');
  console.log('从开始至load完成: ' + ( timing.loadEventEnd - timing.navigationStart)+ 'ms');
  console.log('页面加载耗时: ' + ( timing.loadEventStart - timing.navigationStart)+ 'ms');
  // 至此,我们可以将页面加载过程中的相关耗时详尽的统计输出,分析耗时较长的地方并作出相关的优化。
})()

因为是持久链接,所以domainLookupStart、domainLookupEnd、connectEnd都等于fetchStart,所以Appcache 耗时、DNS 查询耗时、TCP连接耗时都是0。

最后整出来3个指标:第一个对应控制台的DOMContentLoaded,第三个对应控制台的Load

DOM加载时间(timing.domContentLoadedEventStart - timing.navigationStart)
请求时间(timing.responseEnd - timing.requestStart)
页面加载时间(timing.loadEventStart - timing.navigationStart)

统计代码如下:

function performance(){
    var performance = window.performance;
    if (!performance) {return ;} 
    var path = window.location.pathname.replace(/(\d+)/g, '') , 
    timing = performance.timing, 
    DOMLoaded = timing.domContentLoadedEventStart - timing.navigationStart , 
    requestTime = timing.responseEnd - timing.requestStart , 
    pageLoaded = timing.loadEventStart - timing.navigationStart ; 
    _czc.push(['_trackEvent', 'DOMLoaded-time', 'show', path , DOMLoaded, '']) ;
    _czc.push(['_trackEvent', 'requestTime-time', 'show',path, requestTime, '']) ; 
    _czc.push(['_trackEvent', 'pageLoaded-time', 'show', path, pageLoaded, '']) ;
}

四、监测代码加在哪儿

这个是个坑,因为项目采用的是nuxt(vue)的,单页面,但是每个页面都需要统计这些数据,想写在全局。试了好多方案,最后选了一种。

方案1:在mounted里写
刚开始在首页试的,发现要写在window.onload里才能统计到真实数据。因为是单页面,就算在每个页面里写onload,取到的也都是一样的数。

方案2:中间件
这个可以写在全局,但是路由跳转的时候取不到window,设置延时或window.onload也不行。

方案3:插件
写了个js文件,nuxt.config.js配置了ssr: false,设置延时或window.onload还是不行。

方案4:nuxt.config.js加在script标签里。这个方案是可行的,能检测到第一次进入页面时的数据或者是刷新当前页面的数据。

{ innerHTML: "window.onload = function(){var performance = window.performance;if (!performance) {return ;} var path = window.location.pathname.replace(/(\d+)/g, '') , timing = performance.timing, DOMLoaded = timing.domContentLoadedEventStart - timing.navigationStart , requestTime = timing.responseEnd - timing.requestStart , pageLoaded = timing.loadEventStart - timing.navigationStart ; _czc.push(['_trackEvent', 'DOMLoaded-time', 'show', path , DOMLoaded, '']) ; _czc.push(['_trackEvent', 'requestTime-time', 'show',path, requestTime, '']) ; _czc.push(['_trackEvent', 'pageLoaded-time', 'show', path, pageLoaded, '']);}"}

即:

window.onload = function(){
    var performance = window.performance;
    if (!performance) {return ;} 
    var path = window.location.pathname.replace(/(\\d+)/g, '') , 
    timing = performance.timing, 
    DOMLoaded = timing.domContentLoadedEventStart - timing.navigationStart , 
    requestTime = timing.responseEnd - timing.requestStart , 
    pageLoaded = timing.loadEventStart - timing.navigationStart ; 
    _czc.push(['_trackEvent', 'DOMLoaded-time', 'show', path , DOMLoaded, '']) ;
    _czc.push(['_trackEvent', 'requestTime-time', 'show',path, requestTime, '']) ; 
    _czc.push(['_trackEvent', 'pageLoaded-time', 'show', path, pageLoaded, '']) ;
}

遇到的问题:
1、var path = window.location.pathname.replace(/(\d+)/g, ‘’) 这段代码在浏览器控制台能起效,但是统计数据里还是会带着后面的参数id。
发现是转义了匹配上了字母d。。。要加个转义符\

2、统计数据并不全,不是所有的页面都能统计全3个指标,猜想是因为跳转影响了友盟统计。

这个戳单页面数据采集
如果需要准确的数据,可能需要重写 history.replaceState 在方法,在里面加上自定义的统计。

参考

https://segmentfault.com/q/1010000011840948/a-1020000011947156
https://www.cnblogs.com/caizhenbo/p/6679478.html
https://blog.csdn.net/TMQ1225/article/details/80454066
https://www.kancloud.cn/kancloud/javascript-standards-reference/46507#performancegetEntries_137

原文连接

https://www.jianshu.com/p/2bbce858ef0f

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值