Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

perfume.js

Package Overview
Dependencies
Maintainers
1
Versions
157
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

perfume.js - npm Package Compare versions

Comparing version 0.5.0 to 0.6.0

dist/es/emulated-performance.js

9

CHANGELOG.md
# Changelog
## 0.6.0 (2018-3-3)
### Bug Fixes
* **test:** Increased cross-browser tests and separate the native logic from the emulated version [#24c8996](https://github.com/Zizzamia/perfume.js/commit/24c8996fa894e64e928b84ec680e2fa61df4aa99) [#22](https://github.com/Zizzamia/perfume.js/issues/22).
## 0.5.0 (2018-1-14)

@@ -14,4 +21,2 @@

# Changelog
## 0.4.0 (2018-1-7)

@@ -18,0 +23,0 @@

@@ -1,2 +0,3 @@

import ttiPolyfill from "tti-polyfill";
import EmulatedPerformance from "./emulated-performance";
import Performance from "./performance";
var Perfume = /** @class */ (function () {

@@ -18,46 +19,12 @@ function Perfume(options) {

this.metrics = {};
this.ttiPolyfill = ttiPolyfill;
this.config = Object.assign({}, this.config, options);
if (!this.supportsPerfNow) {
global.console.warn(this.config.logPrefix, "Cannot be used in this browser.");
}
this.firstContentfulPaint();
// Init performance implementation
this.perf = Performance.supported() ? new Performance() : new EmulatedPerformance();
this.perf.config = this.config;
// Init First Contentful Paint
this.perf.firstContentfulPaint(this.firstContentfulPaintCb.bind(this));
}
Object.defineProperty(Perfume.prototype, "supportsPerfNow", {
/**
* True if the browser supports the Navigation Timing API.
* @type {boolean}
*/
get: function () {
return window.performance && performance.now ? true : false;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Perfume.prototype, "supportsPerfMark", {
/**
* True if the browser supports the User Timing API.
* Support: developer.mozilla.org/en-US/docs/Web/API/Performance/mark
* @type {boolean}
*/
get: function () {
return window.performance && performance.mark ? true : false;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Perfume.prototype, "supportsPerfObserver", {
/**
* True if the browser supports the PerformanceObserver Interface.
* Support: developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver
* @type {boolean}
*/
get: function () {
return "PerformanceLongTaskTiming" in window;
},
enumerable: true,
configurable: true
});
/**
* Start performance measurement
*
* @param {string} metricName

@@ -69,5 +36,2 @@ */

}
if (!this.supportsPerfMark) {
global.console.warn(this.config.logPrefix, "Timeline won't be marked for \"" + metricName + "\".");
}
if (this.metrics[metricName]) {

@@ -79,8 +43,9 @@ global.console.warn(this.config.logPrefix, "Recording already started.");

end: 0,
start: this.performanceNow(),
start: this.perf.now(),
};
this.mark(metricName, "start");
this.perf.mark(metricName, "start");
};
/**
* End performance measurement
*
* @param {string} metricName

@@ -96,6 +61,5 @@ */

}
this.metrics[metricName].end = this.performanceNow();
this.mark(metricName, "end");
this.measure(metricName, "start", "end");
var duration = this.getDurationByMetric(metricName);
this.metrics[metricName].end = this.perf.now();
this.perf.mark(metricName, "end");
var duration = this.perf.measure(metricName, this.metrics);
if (this.config.logging) {

@@ -110,2 +74,3 @@ this.log(metricName, duration);

* End performance measurement after first paint from the beging of it
*
* @param {string} metricName

@@ -124,2 +89,3 @@ */

* Coloring Text in Browser Console
*
* @param {string} metricName

@@ -139,28 +105,4 @@ * @param {number} duration

/**
* This assumes the user has made only one measurement for the given
* name. Return the first PerformanceEntry objects for the given name.
* @param {string} metricName
*/
Perfume.prototype.getMeasurementForGivenName = function (metricName) {
return performance.getEntriesByName(metricName)[0];
};
/**
* Get the duration of the timing metric or -1 if there a measurement has
* not been made. Use User Timing API results if available, otherwise return
* performance.now() fallback.
* @param {string} metricName
*/
Perfume.prototype.getDurationByMetric = function (metricName) {
if (this.supportsPerfMark) {
var entry = this.getMeasurementForGivenName(metricName);
if (entry && entry.entryType !== "measure") {
return entry.duration;
}
}
var duration = this.metrics[metricName].end - this.metrics[metricName].start;
return duration || -1;
};
/**
* @param {string} metricName
*/
Perfume.prototype.checkMetricName = function (metricName) {

@@ -174,96 +116,28 @@ if (metricName) {

/**
* When performance API available:
* - Returns a DOMHighResTimeStamp, measured in milliseconds, accurate to five
* thousandths of a millisecond (5 microseconds).
* Otherwise:
* - Unlike returns Date.now that is limited to one-millisecond resolution.
* @type {number}
* @param {object} entry
*/
Perfume.prototype.performanceNow = function () {
if (this.supportsPerfMark) {
return window.performance.now();
Perfume.prototype.firstContentfulPaintCb = function (entry) {
if (this.config.firstContentfulPaint) {
this.logFCP(entry.startTime);
}
else {
return Date.now() / 1000;
if (Performance.supported()
&& Performance.supportedLongTask()
&& this.config.timeToInteractive) {
this.perf.timeToInteractive(entry.startTime, this.timeToInteractiveCb.bind(this));
}
};
/**
* @param {string} metricName
* @param {string} type
* @param {number} timeToInteractive
*/
Perfume.prototype.mark = function (metricName, type) {
if (!this.supportsPerfMark) {
return;
Perfume.prototype.timeToInteractiveCb = function (timeToInteractive) {
this.timeToInteractiveDuration = timeToInteractive;
if (this.timeToInteractiveDuration) {
this.log("Time to interactive", this.timeToInteractiveDuration);
}
var mark = "mark_" + metricName + "_" + type;
window.performance.mark(mark);
};
/**
* @param {string} metricName
* @param {string} startMark
* @param {string} endMark
*/
Perfume.prototype.measure = function (metricName, startType, endType) {
if (!this.supportsPerfMark) {
return;
if (this.config.timeToInteractiveCb) {
this.config.timeToInteractiveCb(this.timeToInteractiveDuration);
}
var startMark = "mark_" + metricName + "_" + startType;
var endMark = "mark_" + metricName + "_" + endType;
window.performance.measure(metricName, startMark, endMark);
this.sendTiming("timeToInteractive", this.timeToInteractiveDuration);
};
/**
* First Paint is essentially the paint after which
* the biggest above-the-fold layout change has happened.
*/
Perfume.prototype.firstContentfulPaint = function () {
if (this.supportsPerfObserver) {
var observer = new PerformanceObserver(this.observeFirstContentfulPaint.bind(this));
observer.observe({ entryTypes: ["paint"] });
}
else {
this.timeFirstPaint();
}
};
/**
* PerformanceObserver subscribes to performance events as they happen
* and respond to them asynchronously.
* entry.name will be either 'first-paint' or 'first-contentful-paint'
* @param {object} entryList
*/
Perfume.prototype.observeFirstContentfulPaint = function (entryList) {
for (var _i = 0, _a = entryList.getEntries(); _i < _a.length; _i++) {
var entry = _a[_i];
if (entry.name === "first-contentful-paint") {
if (this.config.firstContentfulPaint) {
this.logFCP(entry.startTime);
}
if (this.config.timeToInteractive) {
this.timeToInteractive(entry.startTime);
}
}
}
};
/**
* http://msdn.microsoft.com/ff974719
* developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming/navigationStart
*/
Perfume.prototype.getFirstPaint = function () {
if (performance) {
var navTiming = performance.timing;
if (navTiming && navTiming.navigationStart !== 0) {
return Date.now() - navTiming.navigationStart;
}
}
return 0;
};
/**
* Uses setTimeout to retrieve FCP
*/
Perfume.prototype.timeFirstPaint = function () {
var _this = this;
setTimeout(function () {
_this.logFCP(_this.getFirstPaint());
});
};
/**
* @param {number} duration

@@ -273,36 +147,6 @@ */

this.firstContentfulPaintDuration = duration;
if (this.firstContentfulPaintDuration) {
this.log("First Contentful Paint", this.firstContentfulPaintDuration);
}
this.log("First Contentful Paint", this.firstContentfulPaintDuration);
this.sendTiming("firstContentfulPaint", this.firstContentfulPaintDuration);
};
/**
* The polyfill exposes a getFirstConsistentlyInteractive() method,
* which returns a promise that resolves with the TTI value.
*
* The getFirstConsistentlyInteractive() method accepts an optional
* startTime configuration option, allowing you to specify a lower bound
* for which you know your app cannot be interactive before.
* By default the polyfill uses DOMContentLoaded as the start time,
* but it's often more accurate to use something like the moment your hero elements
* are visible or the point when you know all your event listeners have been added.
*/
Perfume.prototype.timeToInteractive = function (minValue) {
this.ttiPolyfill.getFirstConsistentlyInteractive({ minValue: minValue })
.then(this.timeToInteractiveResolve.bind(this));
};
/**
* @param {number} timeToInteractive
*/
Perfume.prototype.timeToInteractiveResolve = function (timeToInteractive) {
this.timeToInteractiveDuration = timeToInteractive;
if (this.timeToInteractiveDuration) {
this.log("Time to interactive", this.timeToInteractiveDuration);
}
if (this.config.timeToInteractiveCb) {
this.config.timeToInteractiveCb(timeToInteractive);
}
this.sendTiming("timeToInteractive", this.timeToInteractiveDuration);
};
/**
* Sends the User timing measure to Google Analytics.

@@ -309,0 +153,0 @@ * ga('send', 'timing', [timingCategory], [timingVar], [timingValue])

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tti_polyfill_1 = require("tti-polyfill");
var emulated_performance_1 = require("./emulated-performance");
var performance_1 = require("./performance");
var Perfume = /** @class */ (function () {

@@ -20,46 +21,12 @@ function Perfume(options) {

this.metrics = {};
this.ttiPolyfill = tti_polyfill_1.default;
this.config = Object.assign({}, this.config, options);
if (!this.supportsPerfNow) {
global.console.warn(this.config.logPrefix, "Cannot be used in this browser.");
}
this.firstContentfulPaint();
// Init performance implementation
this.perf = performance_1.default.supported() ? new performance_1.default() : new emulated_performance_1.default();
this.perf.config = this.config;
// Init First Contentful Paint
this.perf.firstContentfulPaint(this.firstContentfulPaintCb.bind(this));
}
Object.defineProperty(Perfume.prototype, "supportsPerfNow", {
/**
* True if the browser supports the Navigation Timing API.
* @type {boolean}
*/
get: function () {
return window.performance && performance.now ? true : false;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Perfume.prototype, "supportsPerfMark", {
/**
* True if the browser supports the User Timing API.
* Support: developer.mozilla.org/en-US/docs/Web/API/Performance/mark
* @type {boolean}
*/
get: function () {
return window.performance && performance.mark ? true : false;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Perfume.prototype, "supportsPerfObserver", {
/**
* True if the browser supports the PerformanceObserver Interface.
* Support: developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver
* @type {boolean}
*/
get: function () {
return "PerformanceLongTaskTiming" in window;
},
enumerable: true,
configurable: true
});
/**
* Start performance measurement
*
* @param {string} metricName

@@ -71,5 +38,2 @@ */

}
if (!this.supportsPerfMark) {
global.console.warn(this.config.logPrefix, "Timeline won't be marked for \"" + metricName + "\".");
}
if (this.metrics[metricName]) {

@@ -81,8 +45,9 @@ global.console.warn(this.config.logPrefix, "Recording already started.");

end: 0,
start: this.performanceNow(),
start: this.perf.now(),
};
this.mark(metricName, "start");
this.perf.mark(metricName, "start");
};
/**
* End performance measurement
*
* @param {string} metricName

@@ -98,6 +63,5 @@ */

}
this.metrics[metricName].end = this.performanceNow();
this.mark(metricName, "end");
this.measure(metricName, "start", "end");
var duration = this.getDurationByMetric(metricName);
this.metrics[metricName].end = this.perf.now();
this.perf.mark(metricName, "end");
var duration = this.perf.measure(metricName, this.metrics);
if (this.config.logging) {

@@ -112,2 +76,3 @@ this.log(metricName, duration);

* End performance measurement after first paint from the beging of it
*
* @param {string} metricName

@@ -126,2 +91,3 @@ */

* Coloring Text in Browser Console
*
* @param {string} metricName

@@ -141,28 +107,4 @@ * @param {number} duration

/**
* This assumes the user has made only one measurement for the given
* name. Return the first PerformanceEntry objects for the given name.
* @param {string} metricName
*/
Perfume.prototype.getMeasurementForGivenName = function (metricName) {
return performance.getEntriesByName(metricName)[0];
};
/**
* Get the duration of the timing metric or -1 if there a measurement has
* not been made. Use User Timing API results if available, otherwise return
* performance.now() fallback.
* @param {string} metricName
*/
Perfume.prototype.getDurationByMetric = function (metricName) {
if (this.supportsPerfMark) {
var entry = this.getMeasurementForGivenName(metricName);
if (entry && entry.entryType !== "measure") {
return entry.duration;
}
}
var duration = this.metrics[metricName].end - this.metrics[metricName].start;
return duration || -1;
};
/**
* @param {string} metricName
*/
Perfume.prototype.checkMetricName = function (metricName) {

@@ -176,96 +118,28 @@ if (metricName) {

/**
* When performance API available:
* - Returns a DOMHighResTimeStamp, measured in milliseconds, accurate to five
* thousandths of a millisecond (5 microseconds).
* Otherwise:
* - Unlike returns Date.now that is limited to one-millisecond resolution.
* @type {number}
* @param {object} entry
*/
Perfume.prototype.performanceNow = function () {
if (this.supportsPerfMark) {
return window.performance.now();
Perfume.prototype.firstContentfulPaintCb = function (entry) {
if (this.config.firstContentfulPaint) {
this.logFCP(entry.startTime);
}
else {
return Date.now() / 1000;
if (performance_1.default.supported()
&& performance_1.default.supportedLongTask()
&& this.config.timeToInteractive) {
this.perf.timeToInteractive(entry.startTime, this.timeToInteractiveCb.bind(this));
}
};
/**
* @param {string} metricName
* @param {string} type
* @param {number} timeToInteractive
*/
Perfume.prototype.mark = function (metricName, type) {
if (!this.supportsPerfMark) {
return;
Perfume.prototype.timeToInteractiveCb = function (timeToInteractive) {
this.timeToInteractiveDuration = timeToInteractive;
if (this.timeToInteractiveDuration) {
this.log("Time to interactive", this.timeToInteractiveDuration);
}
var mark = "mark_" + metricName + "_" + type;
window.performance.mark(mark);
};
/**
* @param {string} metricName
* @param {string} startMark
* @param {string} endMark
*/
Perfume.prototype.measure = function (metricName, startType, endType) {
if (!this.supportsPerfMark) {
return;
if (this.config.timeToInteractiveCb) {
this.config.timeToInteractiveCb(this.timeToInteractiveDuration);
}
var startMark = "mark_" + metricName + "_" + startType;
var endMark = "mark_" + metricName + "_" + endType;
window.performance.measure(metricName, startMark, endMark);
this.sendTiming("timeToInteractive", this.timeToInteractiveDuration);
};
/**
* First Paint is essentially the paint after which
* the biggest above-the-fold layout change has happened.
*/
Perfume.prototype.firstContentfulPaint = function () {
if (this.supportsPerfObserver) {
var observer = new PerformanceObserver(this.observeFirstContentfulPaint.bind(this));
observer.observe({ entryTypes: ["paint"] });
}
else {
this.timeFirstPaint();
}
};
/**
* PerformanceObserver subscribes to performance events as they happen
* and respond to them asynchronously.
* entry.name will be either 'first-paint' or 'first-contentful-paint'
* @param {object} entryList
*/
Perfume.prototype.observeFirstContentfulPaint = function (entryList) {
for (var _i = 0, _a = entryList.getEntries(); _i < _a.length; _i++) {
var entry = _a[_i];
if (entry.name === "first-contentful-paint") {
if (this.config.firstContentfulPaint) {
this.logFCP(entry.startTime);
}
if (this.config.timeToInteractive) {
this.timeToInteractive(entry.startTime);
}
}
}
};
/**
* http://msdn.microsoft.com/ff974719
* developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming/navigationStart
*/
Perfume.prototype.getFirstPaint = function () {
if (performance) {
var navTiming = performance.timing;
if (navTiming && navTiming.navigationStart !== 0) {
return Date.now() - navTiming.navigationStart;
}
}
return 0;
};
/**
* Uses setTimeout to retrieve FCP
*/
Perfume.prototype.timeFirstPaint = function () {
var _this = this;
setTimeout(function () {
_this.logFCP(_this.getFirstPaint());
});
};
/**
* @param {number} duration

@@ -275,36 +149,6 @@ */

this.firstContentfulPaintDuration = duration;
if (this.firstContentfulPaintDuration) {
this.log("First Contentful Paint", this.firstContentfulPaintDuration);
}
this.log("First Contentful Paint", this.firstContentfulPaintDuration);
this.sendTiming("firstContentfulPaint", this.firstContentfulPaintDuration);
};
/**
* The polyfill exposes a getFirstConsistentlyInteractive() method,
* which returns a promise that resolves with the TTI value.
*
* The getFirstConsistentlyInteractive() method accepts an optional
* startTime configuration option, allowing you to specify a lower bound
* for which you know your app cannot be interactive before.
* By default the polyfill uses DOMContentLoaded as the start time,
* but it's often more accurate to use something like the moment your hero elements
* are visible or the point when you know all your event listeners have been added.
*/
Perfume.prototype.timeToInteractive = function (minValue) {
this.ttiPolyfill.getFirstConsistentlyInteractive({ minValue: minValue })
.then(this.timeToInteractiveResolve.bind(this));
};
/**
* @param {number} timeToInteractive
*/
Perfume.prototype.timeToInteractiveResolve = function (timeToInteractive) {
this.timeToInteractiveDuration = timeToInteractive;
if (this.timeToInteractiveDuration) {
this.log("Time to interactive", this.timeToInteractiveDuration);
}
if (this.config.timeToInteractiveCb) {
this.config.timeToInteractiveCb(timeToInteractive);
}
this.sendTiming("timeToInteractive", this.timeToInteractiveDuration);
};
/**
* Sends the User timing measure to Google Analytics.

@@ -311,0 +155,0 @@ * ga('send', 'timing', [timingCategory], [timingVar], [timingValue])

@@ -0,1 +1,73 @@

var EmulatedPerformance = /** @class */ (function () {
function EmulatedPerformance() {
}
/**
* When performance API is not available
* returns Date.now that is limited to one-millisecond resolution.
*
* @type {number}
*/
EmulatedPerformance.prototype.now = function () {
return Date.now() / 1000;
};
/**
* @param {string} metricName
* @param {string} type
*/
EmulatedPerformance.prototype.mark = function (metricName, type) {
global.console.warn(this.config.logPrefix, "Timeline won't be marked for \"" + metricName + "\".");
};
/**
* @param {string} metricName
* @param {object} metrics
*/
EmulatedPerformance.prototype.measure = function (metricName, metrics) {
return this.getDurationByMetric(metricName, metrics);
};
/**
* First Paint is essentially the paint after which
* the biggest above-the-fold layout change has happened.
* Uses setTimeout to retrieve FCP
*
* @param {any} cb
*/
EmulatedPerformance.prototype.firstContentfulPaint = function (cb) {
var _this = this;
setTimeout(function () {
cb(_this.getFirstPaint());
});
};
/**
* Get the duration of the timing metric or -1 if there a measurement has
* not been made by now() fallback.
*
* @param {string} metricName
* @param {metrics} any
*/
EmulatedPerformance.prototype.getDurationByMetric = function (metricName, metrics) {
var duration = metrics[metricName].end - metrics[metricName].start;
return duration || -1;
};
/**
* http://msdn.microsoft.com/ff974719
* developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming/navigationStart
*
* @param {PerformancePaintTiming} performancePaintTiming
*/
EmulatedPerformance.prototype.getFirstPaint = function () {
var navTiming = window.performance.timing;
var performancePaintTiming = {
duration: 0,
entryType: "paint",
name: "first-contentful-paint",
startTime: 0,
};
if (navTiming && navTiming.navigationStart !== 0) {
performancePaintTiming.startTime = Date.now() - navTiming.navigationStart;
}
return performancePaintTiming;
};
return EmulatedPerformance;
}());
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

@@ -28,2 +100,125 @@

var Performance = /** @class */ (function () {
function Performance() {
this.timeToInteractiveDuration = 0;
this.ttiPolyfill = ttiPolyfill;
}
/**
* True if the browser supports the Navigation Timing API,
* User Timing API and the PerformanceObserver Interface.
* Support: developer.mozilla.org/en-US/docs/Web/API/Performance/mark
* Support: developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver
*
* @type {boolean}
*/
Performance.supported = function () {
return window.performance
&& !!performance.now
&& !!performance.mark;
};
/**
* True if the browser supports the PerformanceLongTaskTiming interface.
* Support: developer.mozilla.org/en-US/docs/Web/API/PerformanceLongTaskTiming
*
* @type {boolean}
*/
Performance.supportedLongTask = function () {
return "PerformanceLongTaskTiming" in window;
};
/**
* When performance API available
* returns a DOMHighResTimeStamp, measured in milliseconds, accurate to five
* thousandths of a millisecond (5 microseconds).
* @type {number}
*/
Performance.prototype.now = function () {
return window.performance.now();
};
/**
* @param {string} metricName
* @param {string} type
*/
Performance.prototype.mark = function (metricName, type) {
var mark = "mark_" + metricName + "_" + type;
window.performance.mark(mark);
};
/**
* @param {string} metricName
* @param {object} metrics
* @param {string} endMark
*/
Performance.prototype.measure = function (metricName, metrics) {
var startMark = "mark_" + metricName + "_start";
var endMark = "mark_" + metricName + "_end";
window.performance.measure(metricName, startMark, endMark);
return this.getDurationByMetric(metricName, metrics);
};
/**
* First Paint is essentially the paint after which
* the biggest above-the-fold layout change has happened.
* PerformanceObserver subscribes to performance events as they happen
* and respond to them asynchronously.
* entry.name will be either 'first-paint' or 'first-contentful-paint'
*
* @param {any} cb
*/
Performance.prototype.firstContentfulPaint = function (cb) {
var observer = new PerformanceObserver(this.performanceObserverCb.bind(this, cb));
observer.observe({ entryTypes: ["paint"] });
};
/**
* Get the duration of the timing metric or -1 if there a measurement has
* not been made by the User Timing API
*
* @param {string} metricName
* @param {any} metrics
*/
Performance.prototype.getDurationByMetric = function (metricName, metrics) {
var entry = this.getMeasurementForGivenName(metricName);
if (entry && entry.entryType !== "measure") {
return entry.duration;
}
return -1;
};
/**
* This assumes the user has made only one measurement for the given
* name. Return the first PerformanceEntry objects for the given name.
*
* @param {string} metricName
*/
Performance.prototype.getMeasurementForGivenName = function (metricName) {
return window.performance.getEntriesByName(metricName)[0];
};
/**
* @param {any} cb
* @param {PerformanceObserverEntryList} entryList
*/
Performance.prototype.performanceObserverCb = function (cb, entryList) {
for (var _i = 0, _a = entryList.getEntries(); _i < _a.length; _i++) {
var performancePaintTiming = _a[_i];
if (performancePaintTiming.name === "first-contentful-paint") {
cb(performancePaintTiming);
}
}
};
/**
* The polyfill exposes a getFirstConsistentlyInteractive() method,
* which returns a promise that resolves with the TTI value.
*
* The getFirstConsistentlyInteractive() method accepts an optional
* startTime configuration option, allowing you to specify a lower bound
* for which you know your app cannot be interactive before.
* By default the polyfill uses DOMContentLoaded as the start time,
* but it's often more accurate to use something like the moment your hero elements
* are visible or the point when you know all your event listeners have been added.
*
* @param {number} minValue
* @param {any} cb
*/
Performance.prototype.timeToInteractive = function (minValue, cb) {
this.ttiPolyfill.getFirstConsistentlyInteractive({ minValue: minValue }).then(cb);
};
return Performance;
}());
var Perfume = /** @class */ (function () {

@@ -45,46 +240,12 @@ function Perfume(options) {

this.metrics = {};
this.ttiPolyfill = ttiPolyfill;
this.config = Object.assign({}, this.config, options);
if (!this.supportsPerfNow) {
global.console.warn(this.config.logPrefix, "Cannot be used in this browser.");
}
this.firstContentfulPaint();
// Init performance implementation
this.perf = Performance.supported() ? new Performance() : new EmulatedPerformance();
this.perf.config = this.config;
// Init First Contentful Paint
this.perf.firstContentfulPaint(this.firstContentfulPaintCb.bind(this));
}
Object.defineProperty(Perfume.prototype, "supportsPerfNow", {
/**
* True if the browser supports the Navigation Timing API.
* @type {boolean}
*/
get: function () {
return window.performance && performance.now ? true : false;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Perfume.prototype, "supportsPerfMark", {
/**
* True if the browser supports the User Timing API.
* Support: developer.mozilla.org/en-US/docs/Web/API/Performance/mark
* @type {boolean}
*/
get: function () {
return window.performance && performance.mark ? true : false;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Perfume.prototype, "supportsPerfObserver", {
/**
* True if the browser supports the PerformanceObserver Interface.
* Support: developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver
* @type {boolean}
*/
get: function () {
return "PerformanceLongTaskTiming" in window;
},
enumerable: true,
configurable: true
});
/**
* Start performance measurement
*
* @param {string} metricName

@@ -96,5 +257,2 @@ */

}
if (!this.supportsPerfMark) {
global.console.warn(this.config.logPrefix, "Timeline won't be marked for \"" + metricName + "\".");
}
if (this.metrics[metricName]) {

@@ -106,8 +264,9 @@ global.console.warn(this.config.logPrefix, "Recording already started.");

end: 0,
start: this.performanceNow(),
start: this.perf.now(),
};
this.mark(metricName, "start");
this.perf.mark(metricName, "start");
};
/**
* End performance measurement
*
* @param {string} metricName

@@ -123,6 +282,5 @@ */

}
this.metrics[metricName].end = this.performanceNow();
this.mark(metricName, "end");
this.measure(metricName, "start", "end");
var duration = this.getDurationByMetric(metricName);
this.metrics[metricName].end = this.perf.now();
this.perf.mark(metricName, "end");
var duration = this.perf.measure(metricName, this.metrics);
if (this.config.logging) {

@@ -137,2 +295,3 @@ this.log(metricName, duration);

* End performance measurement after first paint from the beging of it
*
* @param {string} metricName

@@ -151,2 +310,3 @@ */

* Coloring Text in Browser Console
*
* @param {string} metricName

@@ -166,28 +326,4 @@ * @param {number} duration

/**
* This assumes the user has made only one measurement for the given
* name. Return the first PerformanceEntry objects for the given name.
* @param {string} metricName
*/
Perfume.prototype.getMeasurementForGivenName = function (metricName) {
return performance.getEntriesByName(metricName)[0];
};
/**
* Get the duration of the timing metric or -1 if there a measurement has
* not been made. Use User Timing API results if available, otherwise return
* performance.now() fallback.
* @param {string} metricName
*/
Perfume.prototype.getDurationByMetric = function (metricName) {
if (this.supportsPerfMark) {
var entry = this.getMeasurementForGivenName(metricName);
if (entry && entry.entryType !== "measure") {
return entry.duration;
}
}
var duration = this.metrics[metricName].end - this.metrics[metricName].start;
return duration || -1;
};
/**
* @param {string} metricName
*/
Perfume.prototype.checkMetricName = function (metricName) {

@@ -201,96 +337,28 @@ if (metricName) {

/**
* When performance API available:
* - Returns a DOMHighResTimeStamp, measured in milliseconds, accurate to five
* thousandths of a millisecond (5 microseconds).
* Otherwise:
* - Unlike returns Date.now that is limited to one-millisecond resolution.
* @type {number}
* @param {object} entry
*/
Perfume.prototype.performanceNow = function () {
if (this.supportsPerfMark) {
return window.performance.now();
Perfume.prototype.firstContentfulPaintCb = function (entry) {
if (this.config.firstContentfulPaint) {
this.logFCP(entry.startTime);
}
else {
return Date.now() / 1000;
if (Performance.supported()
&& Performance.supportedLongTask()
&& this.config.timeToInteractive) {
this.perf.timeToInteractive(entry.startTime, this.timeToInteractiveCb.bind(this));
}
};
/**
* @param {string} metricName
* @param {string} type
* @param {number} timeToInteractive
*/
Perfume.prototype.mark = function (metricName, type) {
if (!this.supportsPerfMark) {
return;
Perfume.prototype.timeToInteractiveCb = function (timeToInteractive) {
this.timeToInteractiveDuration = timeToInteractive;
if (this.timeToInteractiveDuration) {
this.log("Time to interactive", this.timeToInteractiveDuration);
}
var mark = "mark_" + metricName + "_" + type;
window.performance.mark(mark);
};
/**
* @param {string} metricName
* @param {string} startMark
* @param {string} endMark
*/
Perfume.prototype.measure = function (metricName, startType, endType) {
if (!this.supportsPerfMark) {
return;
if (this.config.timeToInteractiveCb) {
this.config.timeToInteractiveCb(this.timeToInteractiveDuration);
}
var startMark = "mark_" + metricName + "_" + startType;
var endMark = "mark_" + metricName + "_" + endType;
window.performance.measure(metricName, startMark, endMark);
this.sendTiming("timeToInteractive", this.timeToInteractiveDuration);
};
/**
* First Paint is essentially the paint after which
* the biggest above-the-fold layout change has happened.
*/
Perfume.prototype.firstContentfulPaint = function () {
if (this.supportsPerfObserver) {
var observer = new PerformanceObserver(this.observeFirstContentfulPaint.bind(this));
observer.observe({ entryTypes: ["paint"] });
}
else {
this.timeFirstPaint();
}
};
/**
* PerformanceObserver subscribes to performance events as they happen
* and respond to them asynchronously.
* entry.name will be either 'first-paint' or 'first-contentful-paint'
* @param {object} entryList
*/
Perfume.prototype.observeFirstContentfulPaint = function (entryList) {
for (var _i = 0, _a = entryList.getEntries(); _i < _a.length; _i++) {
var entry = _a[_i];
if (entry.name === "first-contentful-paint") {
if (this.config.firstContentfulPaint) {
this.logFCP(entry.startTime);
}
if (this.config.timeToInteractive) {
this.timeToInteractive(entry.startTime);
}
}
}
};
/**
* http://msdn.microsoft.com/ff974719
* developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming/navigationStart
*/
Perfume.prototype.getFirstPaint = function () {
if (performance) {
var navTiming = performance.timing;
if (navTiming && navTiming.navigationStart !== 0) {
return Date.now() - navTiming.navigationStart;
}
}
return 0;
};
/**
* Uses setTimeout to retrieve FCP
*/
Perfume.prototype.timeFirstPaint = function () {
var _this = this;
setTimeout(function () {
_this.logFCP(_this.getFirstPaint());
});
};
/**
* @param {number} duration

@@ -300,36 +368,6 @@ */

this.firstContentfulPaintDuration = duration;
if (this.firstContentfulPaintDuration) {
this.log("First Contentful Paint", this.firstContentfulPaintDuration);
}
this.log("First Contentful Paint", this.firstContentfulPaintDuration);
this.sendTiming("firstContentfulPaint", this.firstContentfulPaintDuration);
};
/**
* The polyfill exposes a getFirstConsistentlyInteractive() method,
* which returns a promise that resolves with the TTI value.
*
* The getFirstConsistentlyInteractive() method accepts an optional
* startTime configuration option, allowing you to specify a lower bound
* for which you know your app cannot be interactive before.
* By default the polyfill uses DOMContentLoaded as the start time,
* but it's often more accurate to use something like the moment your hero elements
* are visible or the point when you know all your event listeners have been added.
*/
Perfume.prototype.timeToInteractive = function (minValue) {
this.ttiPolyfill.getFirstConsistentlyInteractive({ minValue: minValue })
.then(this.timeToInteractiveResolve.bind(this));
};
/**
* @param {number} timeToInteractive
*/
Perfume.prototype.timeToInteractiveResolve = function (timeToInteractive) {
this.timeToInteractiveDuration = timeToInteractive;
if (this.timeToInteractiveDuration) {
this.log("Time to interactive", this.timeToInteractiveDuration);
}
if (this.config.timeToInteractiveCb) {
this.config.timeToInteractiveCb(timeToInteractive);
}
this.sendTiming("timeToInteractive", this.timeToInteractiveDuration);
};
/**
* Sends the User timing measure to Google Analytics.

@@ -336,0 +374,0 @@ * ga('send', 'timing', [timingCategory], [timingVar], [timingValue])

@@ -7,2 +7,74 @@ (function (global, factory) {

var EmulatedPerformance = /** @class */ (function () {
function EmulatedPerformance() {
}
/**
* When performance API is not available
* returns Date.now that is limited to one-millisecond resolution.
*
* @type {number}
*/
EmulatedPerformance.prototype.now = function () {
return Date.now() / 1000;
};
/**
* @param {string} metricName
* @param {string} type
*/
EmulatedPerformance.prototype.mark = function (metricName, type) {
global.console.warn(this.config.logPrefix, "Timeline won't be marked for \"" + metricName + "\".");
};
/**
* @param {string} metricName
* @param {object} metrics
*/
EmulatedPerformance.prototype.measure = function (metricName, metrics) {
return this.getDurationByMetric(metricName, metrics);
};
/**
* First Paint is essentially the paint after which
* the biggest above-the-fold layout change has happened.
* Uses setTimeout to retrieve FCP
*
* @param {any} cb
*/
EmulatedPerformance.prototype.firstContentfulPaint = function (cb) {
var _this = this;
setTimeout(function () {
cb(_this.getFirstPaint());
});
};
/**
* Get the duration of the timing metric or -1 if there a measurement has
* not been made by now() fallback.
*
* @param {string} metricName
* @param {metrics} any
*/
EmulatedPerformance.prototype.getDurationByMetric = function (metricName, metrics) {
var duration = metrics[metricName].end - metrics[metricName].start;
return duration || -1;
};
/**
* http://msdn.microsoft.com/ff974719
* developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming/navigationStart
*
* @param {PerformancePaintTiming} performancePaintTiming
*/
EmulatedPerformance.prototype.getFirstPaint = function () {
var navTiming = window.performance.timing;
var performancePaintTiming = {
duration: 0,
entryType: "paint",
name: "first-contentful-paint",
startTime: 0,
};
if (navTiming && navTiming.navigationStart !== 0) {
performancePaintTiming.startTime = Date.now() - navTiming.navigationStart;
}
return performancePaintTiming;
};
return EmulatedPerformance;
}());
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

@@ -35,2 +107,125 @@

var Performance = /** @class */ (function () {
function Performance() {
this.timeToInteractiveDuration = 0;
this.ttiPolyfill = ttiPolyfill;
}
/**
* True if the browser supports the Navigation Timing API,
* User Timing API and the PerformanceObserver Interface.
* Support: developer.mozilla.org/en-US/docs/Web/API/Performance/mark
* Support: developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver
*
* @type {boolean}
*/
Performance.supported = function () {
return window.performance
&& !!performance.now
&& !!performance.mark;
};
/**
* True if the browser supports the PerformanceLongTaskTiming interface.
* Support: developer.mozilla.org/en-US/docs/Web/API/PerformanceLongTaskTiming
*
* @type {boolean}
*/
Performance.supportedLongTask = function () {
return "PerformanceLongTaskTiming" in window;
};
/**
* When performance API available
* returns a DOMHighResTimeStamp, measured in milliseconds, accurate to five
* thousandths of a millisecond (5 microseconds).
* @type {number}
*/
Performance.prototype.now = function () {
return window.performance.now();
};
/**
* @param {string} metricName
* @param {string} type
*/
Performance.prototype.mark = function (metricName, type) {
var mark = "mark_" + metricName + "_" + type;
window.performance.mark(mark);
};
/**
* @param {string} metricName
* @param {object} metrics
* @param {string} endMark
*/
Performance.prototype.measure = function (metricName, metrics) {
var startMark = "mark_" + metricName + "_start";
var endMark = "mark_" + metricName + "_end";
window.performance.measure(metricName, startMark, endMark);
return this.getDurationByMetric(metricName, metrics);
};
/**
* First Paint is essentially the paint after which
* the biggest above-the-fold layout change has happened.
* PerformanceObserver subscribes to performance events as they happen
* and respond to them asynchronously.
* entry.name will be either 'first-paint' or 'first-contentful-paint'
*
* @param {any} cb
*/
Performance.prototype.firstContentfulPaint = function (cb) {
var observer = new PerformanceObserver(this.performanceObserverCb.bind(this, cb));
observer.observe({ entryTypes: ["paint"] });
};
/**
* Get the duration of the timing metric or -1 if there a measurement has
* not been made by the User Timing API
*
* @param {string} metricName
* @param {any} metrics
*/
Performance.prototype.getDurationByMetric = function (metricName, metrics) {
var entry = this.getMeasurementForGivenName(metricName);
if (entry && entry.entryType !== "measure") {
return entry.duration;
}
return -1;
};
/**
* This assumes the user has made only one measurement for the given
* name. Return the first PerformanceEntry objects for the given name.
*
* @param {string} metricName
*/
Performance.prototype.getMeasurementForGivenName = function (metricName) {
return window.performance.getEntriesByName(metricName)[0];
};
/**
* @param {any} cb
* @param {PerformanceObserverEntryList} entryList
*/
Performance.prototype.performanceObserverCb = function (cb, entryList) {
for (var _i = 0, _a = entryList.getEntries(); _i < _a.length; _i++) {
var performancePaintTiming = _a[_i];
if (performancePaintTiming.name === "first-contentful-paint") {
cb(performancePaintTiming);
}
}
};
/**
* The polyfill exposes a getFirstConsistentlyInteractive() method,
* which returns a promise that resolves with the TTI value.
*
* The getFirstConsistentlyInteractive() method accepts an optional
* startTime configuration option, allowing you to specify a lower bound
* for which you know your app cannot be interactive before.
* By default the polyfill uses DOMContentLoaded as the start time,
* but it's often more accurate to use something like the moment your hero elements
* are visible or the point when you know all your event listeners have been added.
*
* @param {number} minValue
* @param {any} cb
*/
Performance.prototype.timeToInteractive = function (minValue, cb) {
this.ttiPolyfill.getFirstConsistentlyInteractive({ minValue: minValue }).then(cb);
};
return Performance;
}());
var Perfume = /** @class */ (function () {

@@ -52,46 +247,12 @@ function Perfume(options) {

this.metrics = {};
this.ttiPolyfill = ttiPolyfill;
this.config = Object.assign({}, this.config, options);
if (!this.supportsPerfNow) {
global.console.warn(this.config.logPrefix, "Cannot be used in this browser.");
}
this.firstContentfulPaint();
// Init performance implementation
this.perf = Performance.supported() ? new Performance() : new EmulatedPerformance();
this.perf.config = this.config;
// Init First Contentful Paint
this.perf.firstContentfulPaint(this.firstContentfulPaintCb.bind(this));
}
Object.defineProperty(Perfume.prototype, "supportsPerfNow", {
/**
* True if the browser supports the Navigation Timing API.
* @type {boolean}
*/
get: function () {
return window.performance && performance.now ? true : false;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Perfume.prototype, "supportsPerfMark", {
/**
* True if the browser supports the User Timing API.
* Support: developer.mozilla.org/en-US/docs/Web/API/Performance/mark
* @type {boolean}
*/
get: function () {
return window.performance && performance.mark ? true : false;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Perfume.prototype, "supportsPerfObserver", {
/**
* True if the browser supports the PerformanceObserver Interface.
* Support: developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver
* @type {boolean}
*/
get: function () {
return "PerformanceLongTaskTiming" in window;
},
enumerable: true,
configurable: true
});
/**
* Start performance measurement
*
* @param {string} metricName

@@ -103,5 +264,2 @@ */

}
if (!this.supportsPerfMark) {
global.console.warn(this.config.logPrefix, "Timeline won't be marked for \"" + metricName + "\".");
}
if (this.metrics[metricName]) {

@@ -113,8 +271,9 @@ global.console.warn(this.config.logPrefix, "Recording already started.");

end: 0,
start: this.performanceNow(),
start: this.perf.now(),
};
this.mark(metricName, "start");
this.perf.mark(metricName, "start");
};
/**
* End performance measurement
*
* @param {string} metricName

@@ -130,6 +289,5 @@ */

}
this.metrics[metricName].end = this.performanceNow();
this.mark(metricName, "end");
this.measure(metricName, "start", "end");
var duration = this.getDurationByMetric(metricName);
this.metrics[metricName].end = this.perf.now();
this.perf.mark(metricName, "end");
var duration = this.perf.measure(metricName, this.metrics);
if (this.config.logging) {

@@ -144,2 +302,3 @@ this.log(metricName, duration);

* End performance measurement after first paint from the beging of it
*
* @param {string} metricName

@@ -158,2 +317,3 @@ */

* Coloring Text in Browser Console
*
* @param {string} metricName

@@ -173,28 +333,4 @@ * @param {number} duration

/**
* This assumes the user has made only one measurement for the given
* name. Return the first PerformanceEntry objects for the given name.
* @param {string} metricName
*/
Perfume.prototype.getMeasurementForGivenName = function (metricName) {
return performance.getEntriesByName(metricName)[0];
};
/**
* Get the duration of the timing metric or -1 if there a measurement has
* not been made. Use User Timing API results if available, otherwise return
* performance.now() fallback.
* @param {string} metricName
*/
Perfume.prototype.getDurationByMetric = function (metricName) {
if (this.supportsPerfMark) {
var entry = this.getMeasurementForGivenName(metricName);
if (entry && entry.entryType !== "measure") {
return entry.duration;
}
}
var duration = this.metrics[metricName].end - this.metrics[metricName].start;
return duration || -1;
};
/**
* @param {string} metricName
*/
Perfume.prototype.checkMetricName = function (metricName) {

@@ -208,96 +344,28 @@ if (metricName) {

/**
* When performance API available:
* - Returns a DOMHighResTimeStamp, measured in milliseconds, accurate to five
* thousandths of a millisecond (5 microseconds).
* Otherwise:
* - Unlike returns Date.now that is limited to one-millisecond resolution.
* @type {number}
* @param {object} entry
*/
Perfume.prototype.performanceNow = function () {
if (this.supportsPerfMark) {
return window.performance.now();
Perfume.prototype.firstContentfulPaintCb = function (entry) {
if (this.config.firstContentfulPaint) {
this.logFCP(entry.startTime);
}
else {
return Date.now() / 1000;
if (Performance.supported()
&& Performance.supportedLongTask()
&& this.config.timeToInteractive) {
this.perf.timeToInteractive(entry.startTime, this.timeToInteractiveCb.bind(this));
}
};
/**
* @param {string} metricName
* @param {string} type
* @param {number} timeToInteractive
*/
Perfume.prototype.mark = function (metricName, type) {
if (!this.supportsPerfMark) {
return;
Perfume.prototype.timeToInteractiveCb = function (timeToInteractive) {
this.timeToInteractiveDuration = timeToInteractive;
if (this.timeToInteractiveDuration) {
this.log("Time to interactive", this.timeToInteractiveDuration);
}
var mark = "mark_" + metricName + "_" + type;
window.performance.mark(mark);
};
/**
* @param {string} metricName
* @param {string} startMark
* @param {string} endMark
*/
Perfume.prototype.measure = function (metricName, startType, endType) {
if (!this.supportsPerfMark) {
return;
if (this.config.timeToInteractiveCb) {
this.config.timeToInteractiveCb(this.timeToInteractiveDuration);
}
var startMark = "mark_" + metricName + "_" + startType;
var endMark = "mark_" + metricName + "_" + endType;
window.performance.measure(metricName, startMark, endMark);
this.sendTiming("timeToInteractive", this.timeToInteractiveDuration);
};
/**
* First Paint is essentially the paint after which
* the biggest above-the-fold layout change has happened.
*/
Perfume.prototype.firstContentfulPaint = function () {
if (this.supportsPerfObserver) {
var observer = new PerformanceObserver(this.observeFirstContentfulPaint.bind(this));
observer.observe({ entryTypes: ["paint"] });
}
else {
this.timeFirstPaint();
}
};
/**
* PerformanceObserver subscribes to performance events as they happen
* and respond to them asynchronously.
* entry.name will be either 'first-paint' or 'first-contentful-paint'
* @param {object} entryList
*/
Perfume.prototype.observeFirstContentfulPaint = function (entryList) {
for (var _i = 0, _a = entryList.getEntries(); _i < _a.length; _i++) {
var entry = _a[_i];
if (entry.name === "first-contentful-paint") {
if (this.config.firstContentfulPaint) {
this.logFCP(entry.startTime);
}
if (this.config.timeToInteractive) {
this.timeToInteractive(entry.startTime);
}
}
}
};
/**
* http://msdn.microsoft.com/ff974719
* developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming/navigationStart
*/
Perfume.prototype.getFirstPaint = function () {
if (performance) {
var navTiming = performance.timing;
if (navTiming && navTiming.navigationStart !== 0) {
return Date.now() - navTiming.navigationStart;
}
}
return 0;
};
/**
* Uses setTimeout to retrieve FCP
*/
Perfume.prototype.timeFirstPaint = function () {
var _this = this;
setTimeout(function () {
_this.logFCP(_this.getFirstPaint());
});
};
/**
* @param {number} duration

@@ -307,36 +375,6 @@ */

this.firstContentfulPaintDuration = duration;
if (this.firstContentfulPaintDuration) {
this.log("First Contentful Paint", this.firstContentfulPaintDuration);
}
this.log("First Contentful Paint", this.firstContentfulPaintDuration);
this.sendTiming("firstContentfulPaint", this.firstContentfulPaintDuration);
};
/**
* The polyfill exposes a getFirstConsistentlyInteractive() method,
* which returns a promise that resolves with the TTI value.
*
* The getFirstConsistentlyInteractive() method accepts an optional
* startTime configuration option, allowing you to specify a lower bound
* for which you know your app cannot be interactive before.
* By default the polyfill uses DOMContentLoaded as the start time,
* but it's often more accurate to use something like the moment your hero elements
* are visible or the point when you know all your event listeners have been added.
*/
Perfume.prototype.timeToInteractive = function (minValue) {
this.ttiPolyfill.getFirstConsistentlyInteractive({ minValue: minValue })
.then(this.timeToInteractiveResolve.bind(this));
};
/**
* @param {number} timeToInteractive
*/
Perfume.prototype.timeToInteractiveResolve = function (timeToInteractive) {
this.timeToInteractiveDuration = timeToInteractive;
if (this.timeToInteractiveDuration) {
this.log("Time to interactive", this.timeToInteractiveDuration);
}
if (this.config.timeToInteractiveCb) {
this.config.timeToInteractiveCb(timeToInteractive);
}
this.sendTiming("timeToInteractive", this.timeToInteractiveDuration);
};
/**
* Sends the User timing measure to Google Analytics.

@@ -343,0 +381,0 @@ * ga('send', 'timing', [timingCategory], [timingVar], [timingValue])

@@ -21,23 +21,7 @@ declare global {

private metrics;
private ttiPolyfill;
private perf;
constructor(options?: any);
/**
* True if the browser supports the Navigation Timing API.
* @type {boolean}
*/
readonly supportsPerfNow: boolean;
/**
* True if the browser supports the User Timing API.
* Support: developer.mozilla.org/en-US/docs/Web/API/Performance/mark
* @type {boolean}
*/
readonly supportsPerfMark: boolean;
/**
* True if the browser supports the PerformanceObserver Interface.
* Support: developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver
* @type {boolean}
*/
readonly supportsPerfObserver: boolean;
/**
* Start performance measurement
*
* @param {string} metricName

@@ -48,2 +32,3 @@ */

* End performance measurement
*
* @param {string} metricName

@@ -54,2 +39,3 @@ */

* End performance measurement after first paint from the beging of it
*
* @param {string} metricName

@@ -60,2 +46,3 @@ */

* Coloring Text in Browser Console
*
* @param {string} metricName

@@ -66,60 +53,14 @@ * @param {number} duration

/**
* This assumes the user has made only one measurement for the given
* name. Return the first PerformanceEntry objects for the given name.
* @param {string} metricName
*/
private getMeasurementForGivenName(metricName);
/**
* Get the duration of the timing metric or -1 if there a measurement has
* not been made. Use User Timing API results if available, otherwise return
* performance.now() fallback.
* @param {string} metricName
*/
private getDurationByMetric(metricName);
/**
* @param {string} metricName
*/
private checkMetricName(metricName);
/**
* When performance API available:
* - Returns a DOMHighResTimeStamp, measured in milliseconds, accurate to five
* thousandths of a millisecond (5 microseconds).
* Otherwise:
* - Unlike returns Date.now that is limited to one-millisecond resolution.
* @type {number}
* @param {object} entry
*/
private performanceNow();
private firstContentfulPaintCb(entry);
/**
* @param {string} metricName
* @param {string} type
* @param {number} timeToInteractive
*/
private mark(metricName, type);
private timeToInteractiveCb(timeToInteractive);
/**
* @param {string} metricName
* @param {string} startMark
* @param {string} endMark
*/
private measure(metricName, startType, endType);
/**
* First Paint is essentially the paint after which
* the biggest above-the-fold layout change has happened.
*/
private firstContentfulPaint();
/**
* PerformanceObserver subscribes to performance events as they happen
* and respond to them asynchronously.
* entry.name will be either 'first-paint' or 'first-contentful-paint'
* @param {object} entryList
*/
private observeFirstContentfulPaint(entryList);
/**
* http://msdn.microsoft.com/ff974719
* developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming/navigationStart
*/
private getFirstPaint();
/**
* Uses setTimeout to retrieve FCP
*/
private timeFirstPaint();
/**
* @param {number} duration

@@ -129,18 +70,2 @@ */

/**
* The polyfill exposes a getFirstConsistentlyInteractive() method,
* which returns a promise that resolves with the TTI value.
*
* The getFirstConsistentlyInteractive() method accepts an optional
* startTime configuration option, allowing you to specify a lower bound
* for which you know your app cannot be interactive before.
* By default the polyfill uses DOMContentLoaded as the start time,
* but it's often more accurate to use something like the moment your hero elements
* are visible or the point when you know all your event listeners have been added.
*/
private timeToInteractive(minValue);
/**
* @param {number} timeToInteractive
*/
private timeToInteractiveResolve(timeToInteractive);
/**
* Sends the User timing measure to Google Analytics.

@@ -147,0 +72,0 @@ * ga('send', 'timing', [timingCategory], [timingVar], [timingValue])

{
"name": "perfume.js",
"version": "0.5.0",
"description": "",
"keywords": [],
"version": "0.6.0",
"description": "JavaScript library for measuring Short and Long Script, First Contentful Paint (FCP), Time to Interactive (TTI), Component First Paint (CFM), annotating them to the DevTools timeline and reporting the results to Google Analytics.",
"keywords": [
"performance-metrics",
"google-analytics",
"paint",
"perfume",
"metrics",
"javascript-library",
"timeline",
"time-to-interactive",
"first-contentful-paint",
"devtools",
"tti",
"fcp",
"user-timing",
"web-performance",
"web-performance-reports",
"webperf"
],
"main": "dist/perfume.umd.js",

@@ -7,0 +24,0 @@ "module": "dist/perfume.es5.js",

<a href="http://zizzamia.github.io/perfume/"><img src="https://github.com/Zizzamia/perfume.js/blob/master/docs/src/assets/perfume-logo-v0-5-0.png" align="left" width="262" /></a>
# [Perfume.js v0.5.0](http://zizzamia.github.io/perfume/)
[![NPM version](https://badge.fury.io/js/perfume.js.svg)](https://www.npmjs.org/package/perfume.js) [![Build Status](https://travis-ci.org/Zizzamia/perfume.js.svg?branch=master)](https://travis-ci.org/Zizzamia/perfume.js) [![NPM Downloads](http://img.shields.io/npm/dm/perfume.js.svg)](https://www.npmjs.org/package/perfume.js)
# [Perfume.js v0.6.0](http://zizzamia.github.io/perfume/)
[![NPM version](https://badge.fury.io/js/perfume.js.svg)](https://www.npmjs.org/package/perfume.js) [![Build Status](https://travis-ci.org/Zizzamia/perfume.js.svg?branch=master)](https://travis-ci.org/Zizzamia/perfume.js) [![NPM Downloads](http://img.shields.io/npm/dm/perfume.js.svg)](https://www.npmjs.org/package/perfume.js) [![Test Coverage](https://api.codeclimate.com/v1/badges/f813d2f45b274d93b8c5/test_coverage)](https://codeclimate.com/github/Zizzamia/perfume.js/test_coverage)

@@ -94,3 +94,3 @@ > Perfume is a JavaScript library for measuring Short and Long Script, First Contentful Paint ([FCP](https://developers.google.com/web/updates/2017/06/user-centric-performance-metrics#first_paint_and_first_contentful_paint)), Time to Interactive ([TTI](https://developers.google.com/web/tools/lighthouse/audits/time-to-interactive)), Component First Paint (CFM), annotating them to the DevTools timeline and reporting the results to Google Analytics.

fibonacci(400);
perfume.end('fibonacci');
perfume.end('fibonacci');
// ⚡️ Perfume.js: fibonacci 0.14 ms

@@ -107,3 +107,3 @@ ```

$(element).popover('toggle');
perfume.endPaint('togglePopover');
perfume.endPaint('togglePopover');
// ⚡️ Perfume.js: togglePopover 10.54 ms

@@ -124,3 +124,3 @@ ```

const duration = this.perfume.end('fibonacci');
perfume.log('Custom logging', duration);
perfume.log('Custom logging', duration);
// 🍻 Beerjs: Custom logging 0.14 ms

@@ -127,0 +127,0 @@ ```

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc