Add window.performance to the execution tree
This commit is contained in:
@@ -52,7 +52,8 @@ var PhantomasWrapper = function() {
|
||||
'screenshot',
|
||||
//'staticAssets',
|
||||
//'timeToFirst',
|
||||
'waitForSelector'
|
||||
'waitForSelector',
|
||||
'windowPerformance'
|
||||
].join(','),
|
||||
'include-dirs': [
|
||||
'phantomas_custom/core',
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Measure when the page reaches certain states
|
||||
*
|
||||
* @see http://w3c-test.org/webperf/specs/NavigationTiming/#dom-performancetiming-domloading
|
||||
* @see https://developers.google.com/web/fundamentals/performance/critical-rendering-path/measure-crp
|
||||
*/
|
||||
/* global document: true, window: true */
|
||||
'use strict';
|
||||
|
||||
exports.version = '1.0.a';
|
||||
|
||||
exports.module = function(phantomas) {
|
||||
// times below are calculated relative to performance.timing.responseEnd (#117)
|
||||
phantomas.setMetric('domInteractive'); // @desc time it took to parse the HTML and construct the DOM
|
||||
phantomas.setMetric('domContentLoaded'); // @desc time it took to construct both DOM and CSSOM, no stylesheets that are blocking JavaScript execution (i.e. onDOMReady)
|
||||
phantomas.setMetric('domContentLoadedEnd'); // @desc time it took to finish handling of onDOMReady event @unreliable
|
||||
phantomas.setMetric('domComplete'); // @desc time it took to load all page resources, the loading spinner has stopped spinning
|
||||
|
||||
// backend vs frontend time
|
||||
phantomas.setMetric('timeBackend'); // @desc time to the first byte compared to the total loading time [%]
|
||||
phantomas.setMetric('timeFrontend'); // @desc time to window.load compared to the total loading time [%]
|
||||
|
||||
// measure dom... metrics from the moment HTML response was fully received
|
||||
var responseEndTime = Date.now();
|
||||
|
||||
phantomas.on('responseEnd', function() {
|
||||
responseEndTime = Date.now();
|
||||
phantomas.log('Performance timing: responseEnd = %d', responseEndTime);
|
||||
});
|
||||
|
||||
phantomas.on('init', function() {
|
||||
phantomas.evaluate(function(responseEndTime) {
|
||||
(function(phantomas) {
|
||||
phantomas.spyEnabled(false, 'installing window.performance metrics');
|
||||
|
||||
// extend window.performance
|
||||
// "init" event is sometimes fired twice, pass a value set by "responseEnd" event handler (fixes #192)
|
||||
if (typeof window.performance === 'undefined') {
|
||||
window.performance = {
|
||||
timing: {
|
||||
responseEnd: responseEndTime
|
||||
}
|
||||
};
|
||||
|
||||
phantomas.log('Performance timing: emulating window.performance');
|
||||
}
|
||||
else {
|
||||
phantomas.log('Performance timing: using native window.performance');
|
||||
}
|
||||
|
||||
// onDOMReady
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
|
||||
setTimeout(function() {
|
||||
// use NavigationTiming if possible
|
||||
var time = window.performance.timing.domContentLoadedEventEnd ?
|
||||
(window.performance.timing.domContentLoadedEventEnd - window.performance.timing.responseEnd)
|
||||
:
|
||||
(Date.now() - responseEndTime);
|
||||
|
||||
phantomas.setMetric('domContentLoadedEnd', time, true);
|
||||
phantomas.log('Performance timing: document reached "DOMContentLoadedEnd" state after %d ms', time);
|
||||
|
||||
phantomas.pushContext({
|
||||
type: 'domContentLoadedEnd'
|
||||
});
|
||||
}, 0);
|
||||
|
||||
var time = Date.now() - responseEndTime;
|
||||
|
||||
phantomas.setMetric('domContentLoaded', time, true);
|
||||
phantomas.log('Performance timing: document reached "DOMContentLoaded" state after %d ms', time);
|
||||
|
||||
phantomas.pushContext({
|
||||
type: 'domContentLoaded'
|
||||
});
|
||||
});
|
||||
|
||||
// emulate Navigation Timing
|
||||
document.addEventListener('readystatechange', function() {
|
||||
var readyState = document.readyState,
|
||||
responseEndTime = window.performance.timing.responseEnd,
|
||||
time = Date.now() - responseEndTime,
|
||||
metricName;
|
||||
|
||||
// @see http://www.w3.org/TR/html5/dom.html#documentreadystate
|
||||
switch(readyState) {
|
||||
// the browser has finished parsing all of the HTML and DOM construction is complete
|
||||
case 'interactive':
|
||||
metricName = 'domInteractive';
|
||||
break;
|
||||
|
||||
// the processing is complete and all of the resources on the page have finished downloading
|
||||
case 'complete':
|
||||
metricName = 'domComplete';
|
||||
phantomas.log('Performance timing: %j', window.performance.timing);
|
||||
break;
|
||||
|
||||
default:
|
||||
phantomas.log('Performance timing: unhandled "%s" state!', readyState);
|
||||
return;
|
||||
}
|
||||
|
||||
phantomas.setMetric(metricName, time, true);
|
||||
phantomas.log('Performance timing: document reached "%s" state after %d ms', readyState, time);
|
||||
|
||||
phantomas.pushContext({
|
||||
type: metricName
|
||||
});
|
||||
});
|
||||
|
||||
phantomas.spyEnabled(true);
|
||||
})(window.__phantomas);
|
||||
}, responseEndTime);
|
||||
});
|
||||
|
||||
/**
|
||||
* Emit metrics with backend vs frontend time
|
||||
*
|
||||
* Performance Golden Rule:
|
||||
* "80-90% of the end-user response time is spent on the frontend. Start there."
|
||||
*
|
||||
* @see http://www.stevesouders.com/blog/2012/02/10/the-performance-golden-rule/
|
||||
*/
|
||||
phantomas.on('report', function() {
|
||||
// The “backend” time is the time it takes the server to get the first byte back to the client.
|
||||
// The “frontend” time is measured from the last byte of the response (responseEnd) until all resources are fetched (domComplete)
|
||||
var backendTime = parseInt(phantomas.getMetric('timeToFirstByte'), 10),
|
||||
frontendTime = parseInt(phantomas.getMetric('domComplete'), 10),
|
||||
totalTime = backendTime + frontendTime,
|
||||
backendTimePercentage;
|
||||
|
||||
if (totalTime === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
backendTimePercentage = Math.round(backendTime / totalTime * 100);
|
||||
|
||||
phantomas.setMetric('timeBackend', backendTimePercentage);
|
||||
phantomas.setMetric('timeFrontend', 100 - backendTimePercentage);
|
||||
|
||||
phantomas.log('Performance timing: backend vs frontend time - %d% / %d%', backendTimePercentage, 100 - backendTimePercentage);
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user