timing.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /**
  2. * Timing.js 1.2.0
  3. * Copyright 2016 Addy Osmani
  4. * @ref https://github.com/addyosmani/timing.js/blob/master/timing.js
  5. */
  6. (function(window) {
  7. 'use strict';
  8. /**
  9. * Navigation Timing API helpers
  10. * timing.getTimes();
  11. **/
  12. window.timing = window.timing || {
  13. /**
  14. * Outputs extended measurements using Navigation Timing API
  15. * @param Object opts Options (simple (bool) - opts out of full data view)
  16. * @return Object measurements
  17. */
  18. getTimes: function(opts) {
  19. var performance = window.performance || window.webkitPerformance || window.msPerformance || window.mozPerformance;
  20. if (performance === undefined) {
  21. return false;
  22. }
  23. var timing = performance.timing;
  24. var api = {};
  25. opts = opts || {};
  26. if (timing) {
  27. if(opts && !opts.simple) {
  28. for (var k in timing) {
  29. // hasOwnProperty does not work because properties are
  30. // added by modifying the object prototype
  31. if(isNumeric(timing[k])) {
  32. api[k] = parseFloat(timing[k]);
  33. }
  34. }
  35. }
  36. // Time to first paint
  37. if (api.firstPaint === undefined) {
  38. // All times are relative times to the start time within the
  39. // same objects
  40. var firstPaint = 0;
  41. // IE
  42. if (typeof timing.msFirstPaint === 'number') {
  43. firstPaint = timing.msFirstPaint;
  44. api.firstPaintTime = firstPaint - timing.navigationStart;
  45. } else if (performance.getEntriesByName !== undefined) {
  46. var firstPaintPerformanceEntry = performance.getEntriesByName('first-paint');
  47. if (firstPaintPerformanceEntry.length === 1) {
  48. var firstPaintTime = firstPaintPerformanceEntry[0].startTime;
  49. firstPaint = performance.timeOrigin + firstPaintTime;
  50. api.firstPaintTime = firstPaintTime;
  51. }
  52. }
  53. if (opts && !opts.simple) {
  54. api.firstPaint = firstPaint;
  55. }
  56. }
  57. // Total time from start to load
  58. api.loadTime = timing.loadEventEnd - timing.fetchStart;
  59. // Time spent constructing the DOM tree
  60. api.domReadyTime = timing.domComplete - timing.domInteractive;
  61. // Time consumed preparing the new page
  62. api.readyStart = timing.fetchStart - timing.navigationStart;
  63. // Time spent during redirection
  64. api.redirectTime = timing.redirectEnd - timing.redirectStart;
  65. // AppCache
  66. api.appcacheTime = timing.domainLookupStart - timing.fetchStart;
  67. // Time spent unloading documents
  68. api.unloadEventTime = timing.unloadEventEnd - timing.unloadEventStart;
  69. // DNS query time
  70. api.lookupDomainTime = timing.domainLookupEnd - timing.domainLookupStart;
  71. // TCP connection time
  72. api.connectTime = timing.connectEnd - timing.connectStart;
  73. // Time spent during the request
  74. api.requestTime = timing.responseEnd - timing.requestStart;
  75. // Request to completion of the DOM loading
  76. api.initDomTreeTime = timing.domInteractive - timing.responseEnd;
  77. // Load event time
  78. api.loadEventTime = timing.loadEventEnd - timing.loadEventStart;
  79. }
  80. return api;
  81. },
  82. /**
  83. * Uses console.table() to print a complete table of timing information
  84. * @param Object opts Options (simple (bool) - opts out of full data view)
  85. */
  86. printTable: function(opts) {
  87. var table = {};
  88. var data = this.getTimes(opts) || {};
  89. Object.keys(data).sort().forEach(function(k) {
  90. table[k] = {
  91. ms: data[k],
  92. s: +((data[k] / 1000).toFixed(2))
  93. };
  94. });
  95. console.table(table);
  96. },
  97. /**
  98. * Uses console.table() to print a summary table of timing information
  99. */
  100. printSimpleTable: function() {
  101. this.printTable({simple: true});
  102. }
  103. };
  104. function isNumeric(n) {
  105. return !isNaN(parseFloat(n)) && isFinite(n);
  106. }
  107. // Expose as a commonjs module
  108. if (typeof module !== 'undefined' && module.exports) {
  109. module.exports = window.timing;
  110. }
  111. })(typeof window !== 'undefined' ? window : {});