试炼之石:Performance

最近在阅读 Vue 的源码的时候去溜达了一圈之前没有关注过的几个 API,好比 mark、measure 等等,因而总结一下前端监控利器 performance 相关的知识。前端

何为试炼之石?

可能有些同窗不太了解这个 API,由于其实说实话,日常也不会接触这些,可是这倒是一个颇有用的 API。咱们能够利用这个 API 完成对页面的性能表现达到十分精确的度量和控制。git

下面呢,咱们将会一块儿领略一下 performance 的魅力,关于 performance 的 API 等等的信息,网上其实说的已经很是多了,这里就再也不赘述,有兴趣的能够自行查阅。github

耗时统计

在 performance 中的 timing 对象里,存储了各类与浏览器性能有关的时间数据,咱们能够经过其中的一些属性来获取到浏览器在不一样阶段处理网页的耗时统计。web

const { timing } = performance;
const t = {};

// DNS 查询时间
t.dns = timing.domainLookupEnd - timing.domainLookupStart;
// 解析 DOM 树时间
t.dom = timing.domComplete - timing.domInteractive;
// 重定向时间
t.redirect = timing.redirectEnd - timing.redirectStart;
// 请求耗时
t.request = timing.responseEnd - timing.requestStart;
// 白屏时间
t.wait = timing.responseStart - timing.navigationStart;
复制代码

其实咱们能从这些时间里还可以获得很是多的信息,上面都是一些很经常使用的时间,咱们能够从这些信息中获知整个页面的总体性能。segmentfault

好比说,当DNS 查询时间长时,这时候你就要考虑是否是使用的域名太多了,或者有没有作 DNS 预解析, 关于 DNS 预解析要注意的是在 HTTP 协议下 a 标签是默认开启的,而 HTTPS 是默认关闭的,须要本身开启。数组

当重定向时间长的时候,你就能够去看看代码里这样的状况,好比说 https://baidu.com 就会重定向到 https://www.baidu.com,固然了,重定向的状况不止这一种,还须要根据自身项目去优化重定向的时间。浏览器

当 DOM 解析时间过长的时候,你就要考虑你的 HTML 的结构是否是不合理。咱们能够经过不一样的时间去检测页面的各类性能,而后针对性的进行修改。微信

打点分析

先看一段 Vue 的源码:dom

const perf = inBrowser && window.performance
/* istanbul ignore if */
if (
  perf &&
  perf.mark &&
  perf.measure &&
  perf.clearMarks &&
  perf.clearMeasures
) {
  mark = tag => perf.mark(tag)
  measure = (name, startTag, endTag) => {
    perf.measure(name, startTag, endTag)
    perf.clearMarks(startTag)
    perf.clearMarks(endTag)
    perf.clearMeasures(name)
  }
}
复制代码

能够看到,其实它封装的两个函数中使用到的就是 performance 中的 mark、measure、clearMarks 以及 clearMeasures 几个函数。前端性能

performance.mark() 和 performance.clearMarks() 是一组函数,咱们能够经过使用 performance.mark() 来标记时间戳,咱们能够经过这些时间戳的名字来计算两个时间戳中间所花费的时间。

而这样的计算方式是否是看着有点熟,是的,在 console 里的 time 和 timeEnd 也可以计时,可是没有 mark 和 measure 灵活。看下面的例子:

function per() {
  performance.mark('per_begin');
  for(const a = 1; a < 10000;a++) {}
  performance.mark('per_end');
}
per();  // 这时候咱们调用 performance.getEntriesByType('mark') 就能够看到刚刚咱们标记的两个时间戳了
// 咱们使用 measure 来计算这两个标记点之间所消耗的时间
performance.measure('per', 'per_begin', 'per_end'); // 经过 performance.getEntriesByName('per') 就能够看到 measure 的时间了
复制代码

Vue 的源码中对这两个方法进行了封装,从实验中咱们可以看到咱们每次打点以及计算都会在 performance 里留下记录,Vue 封装的方法在计算完成以后将记录清除掉了。

这里有些同窗可能就有点困惑了,你 measure 计算的时候计算了就直接 clear 了,这不就白计算了么?其实,在官方的 devTools 里使用了 PerformanceObserver 去监听 performance 的动做,因此监听到取完值,删掉也就没什么了。

就好比说这样:

const observer = new PerformanceObserver(list => {
    list.getEntries().forEach(entry => {
        console.log(`${entry.name}: ${entry.duration}`);
    });
});
observer.observe({
    entryTypes: ['measure']
});
复制代码

这样当咱们调用 performance.measure 就会触发这个回调函数了。

资源监控

咱们对前端的监控主要是两个方面。

第一就是运行错误,这个很明显就是咱们代码写得有问题,出现了 bug,咱们能够在一些能够预知返回结果的地方主动判断函数运行是否正确,其次咱们能够经过 try...catch... 或者是 window.onerror 等方法来进行错误的监控。

第二个方面就是对前端加载的资源进行监控,比较经常使用的方法有 Object.onerror 来捕获错误,要注意的是资源的错误不会冒泡,就是说 window 是捕获不到的,那么还有些什么其余办法呢?固然有,下面说的一种资源监控的方式就要利用到咱们的 performance 了。

顺便提一嘴,前端的错误咱们能够经过好比说 Ajax 的方式上报,可是呢?写 Ajax 仍是比较烦的,你还能够经过 Image 对象上报错误。好了,不扯远了,咱们继续看 performance 怎么监控资源。

咱们随便打开一个网站,就以掘金为例,咱们打开浏览器控制台。

// 在控制台输入
performance.getEntries();
复制代码

咱们能够获得下面的输出:

这个 API 返回的是所有加载成功的资源,那么同时咱们能够经过 document 去拿到咱们要加载的全部资源。

这时候,咱们就可以经过这两个数组来看资源的加载状况了。

总结

performance 这个 API 出来时间也很长了,可是之前一直没有了解过这个 API,在阅读源码的过程当中才看到,属于查缺补漏。

关于 performance 的相关资源都在下面,有兴趣的能够看看:


文 / 小烜同窗

本文已由做者受权发布,版权属于创宇前端。欢迎注明出处转载本文。本文连接:knownsec-fed.com/2018-08-09-…

想要看到更多来自知道创宇开发一线的分享,请搜索关注咱们的微信公众号:创宇前端(KnownsecFED)。欢迎留言讨论,咱们会尽量回复。

感谢您的阅读。

相关文章
相关标签/搜索