window.performance

  1. // 兼容性写法
  2. const performance = window.performance ||
  3. window.msPerformance ||
  4. window.webkitPerformance;

image.png

  • usedJSHeapSize
    JS 对象(包括V8引擎内部对象)占用的内存
  • totalJSHeapSize
    可使用的内存
  • jsHeapSizeLimit
    内存大小限制

    performance.navigation(我从哪里来)

  • redirectCount
    如果有重定向的话,页面通过几次重定向跳转而来

  • type

    • 0 即 TYPE_NAVIGATENEXT 正常进入的页面(非刷新、非重定向等)
    • 1 即 TYPE_RELOAD 通过 window.location.reload() 刷新的页面
    • 2 即 TYPE_BACK_FORWARD 通过浏览器的前进后退按钮进入的页面(历史记录)
    • 255 即 TYPE_UNDEFINED 非以上方式进入的页面

      performance.timing(时间)

      image.png

      各字段的含义如下:

  • startTime:有些浏览器实现为navigationStart,代表浏览器开始unload前一个页面文档的开始时间节点。比如我们当前正在浏览baidu.com,在地址栏输入google.com并回车,浏览器的执行动作依次为:unload当前文档(即http://baidu.com)->请求下一文档(即http://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事件触发和结束的时间节点

    计算性能指标

    单位: ms 毫秒

  • DNS查询耗时 = domainLookupEnd - domainLookupStart

  • TCP链接耗时 = connectEnd - connectStart
  • request请求耗时 = responseEnd - responseStart
  • 解析dom树耗时 = domComplete - domInteractive
  • 白屏时间 = domLoading - fetchStart
  • domready时间 = domContentLoadedEventEnd - fetchStart
  • onload时间 = loadEventEnd - fetchStart ```javascript 所以根据上面的时间点,我们可以计算常规的性能值,如下: (使用该api时需要在页面完全加载完成之后才能使用,最简单的办法是在window.onload事件中读取各种数据,因为很多值必须在页面完全加载之后才能得出。)

var timing = window.performance && window.performance.timing; var navigation = window.performance && window.performance.navigation;

重定向次数: var redirectCount = navigation && navigation.redirectCount;

跳转耗时: var redirect = timing.redirectEnd - timing.redirectStart;

APP CACHE 耗时: var appcache = Math.max(timing.domainLookupStart - timing.fetchStart, 0);

DNS 解析耗时: var dns = timing.domainLookupEnd - timing.domainLookupStart;

TCP 链接耗时: var conn = timing.connectEnd - timing.connectStart;

等待服务器响应耗时(注意是否存在cache): var request = timing.responseStart - timing.requestStart;

内容加载耗时(注意是否存在cache): var response = timing.responseEnd - timing.responseStart;

总体网络交互耗时,即开始跳转到服务器资源下载完成: var network = timing.responseEnd - timing.navigationStart;

渲染处理: var processing = (timing.domComplete || timing.domLoading) - timing.domLoading;

抛出 load 事件: var load = timing.loadEventEnd - timing.loadEventStart;

总耗时: var total = (timing.loadEventEnd || timing.loadEventStart || timing.domComplete || timing.domLoading) - timing.navigationStart;

可交互: var active = timing.domInteractive - timing.navigationStart;

请求响应耗时,即 T0,注意cache: var t0 = timing.responseStart - timing.navigationStart;

白屏时间 = domLoading - fetchStart var t1 = timing.domLoading - timing.fetchStart;

首次出现内容,即 T2: var t2 = timing.domLoading - timing.navigationStart;

内容加载完毕,即 T3: var t3 = timing.loadEventEnd - timing.navigationStart;

  1. <a name="z7ht3"></a>
  2. ## 指标分析
  3. ```javascript
  4. ;
  5. (function() {
  6. handleAddListener('load', getTiming)
  7. function handleAddListener(type, fn) {
  8. if(window.addEventListener) {
  9. window.addEventListener(type, fn)
  10. } else {
  11. window.attachEvent('on' + type, fn)
  12. }
  13. }
  14. function getTiming() {
  15. try {
  16. var time = performance.timing;
  17. var timingObj = {};
  18. var loadTime = (time.loadEventEnd - time.loadEventStart) / 1000;
  19. if(loadTime < 0) {
  20. setTimeout(function() {
  21. getTiming();
  22. }, 200);
  23. return;
  24. }
  25. timingObj['重定向时间'] = (time.redirectEnd - time.redirectStart) / 1000;
  26. timingObj['DNS解析时间'] = (time.domainLookupEnd - time.domainLookupStart) / 1000;
  27. timingObj['TCP完成握手时间'] = (time.connectEnd - time.connectStart) / 1000;
  28. timingObj['HTTP请求响应完成时间'] = (time.responseEnd - time.requestStart) / 1000;
  29. timingObj['DOM开始加载前所花费时间'] = (time.responseEnd - time.navigationStart) / 1000;
  30. timingObj['DOM加载完成时间'] = (time.domComplete - time.domLoading) / 1000;
  31. timingObj['DOM结构解析完成时间'] = (time.domInteractive - time.domLoading) / 1000;
  32. timingObj['脚本加载时间'] = (time.domContentLoadedEventEnd - time.domContentLoadedEventStart) / 1000;
  33. timingObj['onload事件时间'] = (time.loadEventEnd - time.loadEventStart) / 1000;
  34. timingObj['页面完全加载时间'] = (timingObj['重定向时间'] + timingObj['DNS解析时间'] + timingObj['TCP完成握手时间'] + timingObj['HTTP请求响应完成时间'] + timingObj['DOM结构解析完成时间'] + timingObj['DOM加载完成时间']);
  35. for(item in timingObj) {
  36. console.log(item + ":" + timingObj[item] + '毫秒(ms)');
  37. }
  38. console.log(performance.timing);
  39. } catch(e) {
  40. console.log(timingObj)
  41. console.log(performance.timing);
  42. }
  43. }
  44. })();
  45. <!DOCTYPE html>
  46. <html>
  47. <head>
  48. <meta charset="utf-8" />
  49. <title></title>
  50. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  51. <link rel="stylesheet" type="text/css" href="//cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" />
  52. <script src=""></script>
  53. <script type="text/javascript" src=""></script>
  54. </head>
  55. <body>
  56. </body>
  57. </html>

👉白屏\首屏时间

参考链接
白屏时间\首屏时间 还是要具体问题具体分析, 计算方式上略有差异, 采用较多得还是首屏时间(白屏时间对用户来说意义不大)
白屏时间
页面开始请求,到 页面刚开始显示内容,叫做白屏时间
前端性能监控 - 图3

  1. <script>
  2. // 白屏时间
  3. const whiteScreenTime = new Date().getTime() - performance.timing.navigationStart
  4. console.log('whiteScreenTime=', whiteScreenTime);
  5. </script>

首屏时间
首屏时间是指,在不滚动屏幕下的前提下,用户看到完整第一屏内容花费的时间
首屏内容完全加载完成,才叫首屏,而不是出现内容,或者部分元素没有展示
首屏时间一般在 5秒以内是优秀,10秒以内可接受,10s 以后根本不能忍
前端性能监控 - 图4

  1. 首屏时间 = firstScreen - performance.timing.navigationStart

问题是,首屏线在哪里啊
情况分很多种,不同的场景,有不同的计算方式,我们需要根据自己的实际情况去选择相应的方法

  1. 标记首屏标签模块

这种计算方式比较简单,通过在 html 文档中,在首屏线的位置,添加脚本的方式,去获取这个位置的时间
那在哪里添加呢?
首屏线其实我们只能大约估摸一个位置,并不能十分精确地适配任何屏幕的手机
因为手机屏大小不一,绘制得深度不一样, 我们取的位置可能在 首屏线之上,可能在 首屏线之下,只能得到一个大约的值
但是并不需要太精确的数字,大小屏首屏内容反正不会差太多

  1. 统计首屏最慢图片加载时间
  2. 自定义模块计算法

最简单的方法
onload 事件在对象被加载后发生。
window.onload() 方法用于在网页加载完毕后立刻执行的操作,即当 HTML 文档加载完毕后,立刻执行某个方法。
onload 最常用于 元素中,用于在网页完全加载所有内容(包括图像、脚本文件、CSS 文件等)后执行脚本。

  1. // 首屏时间
  2. window.onload = function() {
  3. const firstScreenTime = new Date().getTime() - performance.timing.navigationStart
  4. console.log('firstScreenTime=', firstScreenTime);
  5. }