fixing jshint part 2
This commit is contained in:
parent
a8ad24727c
commit
6c1ce7aad5
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env node
|
||||
var Runner = require("../lib/runner");
|
||||
var Runner = require('../lib/runner');
|
||||
|
||||
var r = new Runner();
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
* and other contributors
|
||||
* Released under the Apache 2.0 License
|
||||
*/
|
||||
var util = require('../../util');
|
||||
var Aggregator = require('../../aggregator');
|
||||
|
||||
module.exports = new Aggregator('gpsi.gscore', 'Google Page Speed Insights Score',
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ exports.processPage = function(pageData) {
|
|||
var timings = Object.keys(entry.timings);
|
||||
|
||||
for (var i = 0; i < timings.length; i++) {
|
||||
if (timings[i] === 'comment') continue;
|
||||
if (timings[i] === 'comment') {
|
||||
continue;
|
||||
}
|
||||
if (timeMetrics.hasOwnProperty(timings[i])) {
|
||||
timeMetrics[timings[i]].push(Number(entry.timings[timings[i]]));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
* and other contributors
|
||||
* Released under the Apache 2.0 License
|
||||
*/
|
||||
var util = require('../../util');
|
||||
var Aggregator = require('../../aggregator');
|
||||
|
||||
module.exports = new Aggregator('har.pageWeight', 'Total page weight (including all assets) from HAR',
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ module.exports = new Aggregator('browserScaledImages',
|
|||
if (pageData.yslow) {
|
||||
if (pageData.yslow.g.avoidscalingimages) {
|
||||
this.stats.push(pageData.yslow.g.avoidscalingimages.components.length);
|
||||
} else this.stats.push(0);
|
||||
} else {
|
||||
this.stats.push(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ module.exports = new Aggregator('criticalPathScore',
|
|||
'', 1,
|
||||
function(pageData) {
|
||||
if (pageData.yslow) {
|
||||
if (pageData.yslow.g.criticalpath)
|
||||
if (pageData.yslow.g.criticalpath) {
|
||||
this.stats.push(pageData.yslow.g.criticalpath.score);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ module.exports = new Aggregator('cssWeight', 'CSS Weight',
|
|||
// also YSlow/PhantomJs don't know about compressed size
|
||||
var self = this;
|
||||
pageData.yslow.comps.forEach(function(comp) {
|
||||
if (comp.type === 'css')
|
||||
if (comp.type === 'css') {
|
||||
self.stats.push(comp.size);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ module.exports = new Aggregator('cssWeightPerPage', 'CSS File Weight Per Page',
|
|||
// also YSlow/PhantomJs don't know about compressed size
|
||||
var size = 0;
|
||||
pageData.yslow.comps.forEach(function(comp) {
|
||||
if (comp.type === 'css')
|
||||
if (comp.type === 'css') {
|
||||
size += comp.size;
|
||||
}
|
||||
});
|
||||
this.stats.push(size);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ module.exports = new Aggregator('docWeight', 'Document Weight',
|
|||
// also YSlow/PhantomJs don't know about compressed size
|
||||
var self = this;
|
||||
pageData.yslow.comps.forEach(function(comp) {
|
||||
if (comp.type === 'doc')
|
||||
if (comp.type === 'doc') {
|
||||
self.stats.push(comp.size);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ module.exports = new Aggregator('domElements', 'Number of DOM elements',
|
|||
if (pageData.yslow) {
|
||||
if (pageData.yslow.g.mindom) {
|
||||
this.stats.push(pageData.yslow.g.mindom.components.length);
|
||||
} else this.stats.push(0);
|
||||
} else {
|
||||
this.stats.push(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ module.exports = new Aggregator('imageWeight', 'Image Weight',
|
|||
// also YSlow/PhantomJs don't know about compressed size
|
||||
var self = this;
|
||||
pageData.yslow.comps.forEach(function(comp) {
|
||||
if (comp.type === 'image')
|
||||
if (comp.type === 'image') {
|
||||
self.stats.push(comp.size);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ module.exports = new Aggregator('imagesWeightPerPage', 'Images Weight Per Page',
|
|||
// also YSlow/PhantomJs don't know about compressed size
|
||||
var size = 0;
|
||||
pageData.yslow.comps.forEach(function(comp) {
|
||||
if (comp.type === 'image')
|
||||
if (comp.type === 'image') {
|
||||
size += comp.size;
|
||||
}
|
||||
});
|
||||
this.stats.push(size);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ module.exports = new Aggregator('jsSyncInHead',
|
|||
if (pageData.yslow) {
|
||||
if (pageData.yslow.g.syncjsinhead) {
|
||||
this.stats.push(pageData.yslow.g.syncjsinhead.components.length);
|
||||
} else this.stats.push(0);
|
||||
} else {
|
||||
this.stats.push(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ module.exports = new Aggregator('jsWeight', 'JS Weight',
|
|||
// also YSlow/PhantomJs don't know about compressed size
|
||||
var self = this;
|
||||
pageData.yslow.comps.forEach(function(comp) {
|
||||
if (comp.type === 'js')
|
||||
if (comp.type === 'js') {
|
||||
self.stats.push(comp.size);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ module.exports = new Aggregator('jsWeightPerPage', 'JS File Weight Per Page',
|
|||
// also YSlow/PhantomJs don't know about compressed size
|
||||
var size = 0;
|
||||
pageData.yslow.comps.forEach(function(comp) {
|
||||
if (comp.type === 'js')
|
||||
if (comp.type === 'js') {
|
||||
size += comp.size;
|
||||
}
|
||||
});
|
||||
this.stats.push(size);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,14 +12,15 @@ module.exports = new Aggregator('maxRequestsPerHost', 'Max requests per domain',
|
|||
'', 2,
|
||||
function(pageData) {
|
||||
if (pageData.yslow) {
|
||||
var hostAndRequests = util.getAssetsPerDomain(pageData.yslow.comps),
|
||||
keys = Object.keys(hostAndRequests),
|
||||
maxRequestsPerHost = 0;
|
||||
var hostAndRequests = util.getAssetsPerDomain(pageData.yslow.comps);
|
||||
var keys = Object.keys(hostAndRequests);
|
||||
var maxRequestsPerHost = 0;
|
||||
|
||||
// take the hosts with the most requests
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
if (hostAndRequests[keys[i]] > maxRequestsPerHost)
|
||||
if (hostAndRequests[keys[i]] > maxRequestsPerHost) {
|
||||
maxRequestsPerHost = hostAndRequests[keys[i]];
|
||||
}
|
||||
}
|
||||
this.stats.push(maxRequestsPerHost);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ module.exports = new Aggregator('pagesWithSPOF', 'Pages with SPOF',
|
|||
if (pageData.yslow) {
|
||||
if (pageData.yslow.g.spof) {
|
||||
this.stats.push(1);
|
||||
} else this.stats.push(0);
|
||||
} else {
|
||||
this.stats.push(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ module.exports = new Aggregator('redirectsPerPage', 'Redirects Per Page',
|
|||
if (pageData.yslow) {
|
||||
if (pageData.yslow.g.redirects) {
|
||||
this.stats.push(pageData.yslow.g.redirects.components.length);
|
||||
} else this.stats.push(0);
|
||||
} else {
|
||||
this.stats.push(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ module.exports = new Aggregator('requests', 'Number of requests per page',
|
|||
'Fewer requests are always faster than many requests.',
|
||||
'', 1,
|
||||
function (pageData) {
|
||||
if (pageData.yslow)
|
||||
if (pageData.yslow) {
|
||||
this.stats.push(pageData.yslow.r);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ module.exports = new Aggregator('requestsWithoutExpires',
|
|||
if (pageData.yslow) {
|
||||
var requestsWithoutExpire = 0;
|
||||
pageData.yslow.comps.forEach(function(comp) {
|
||||
if (util.getCacheTime(comp) === 0)
|
||||
if (util.getCacheTime(comp) === 0) {
|
||||
requestsWithoutExpire++;
|
||||
}
|
||||
});
|
||||
|
||||
this.stats.push(requestsWithoutExpire);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ module.exports = new Aggregator('ruleScore', 'Rule Score',
|
|||
'The sitespeed.io total rule score for all the pages',
|
||||
'', 0,
|
||||
function (pageData) {
|
||||
if (pageData.yslow)
|
||||
if (pageData.yslow) {
|
||||
this.stats.push(pageData.yslow.o);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,14 +12,15 @@ module.exports = new Aggregator('singleDomainRequests', 'Domains with only one r
|
|||
'', 2,
|
||||
function (pageData) {
|
||||
if (pageData.yslow) {
|
||||
var hostAndRequests = util.getAssetsPerDomain(pageData.yslow.comps),
|
||||
keys = Object.keys(hostAndRequests),
|
||||
domainsWithOneRequest = 0;
|
||||
var hostAndRequests = util.getAssetsPerDomain(pageData.yslow.comps);
|
||||
var keys = Object.keys(hostAndRequests);
|
||||
var domainsWithOneRequest = 0;
|
||||
|
||||
// take the hosts with the most requests
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
if (hostAndRequests[keys[i]] === 1)
|
||||
if (hostAndRequests[keys[i]] === 1) {
|
||||
domainsWithOneRequest++;
|
||||
}
|
||||
}
|
||||
this.stats.push(domainsWithOneRequest);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ module.exports = new Aggregator('spofPerPage',
|
|||
if (pageData.yslow) {
|
||||
if (pageData.yslow.g.spof) {
|
||||
this.stats.push(pageData.yslow.g.spof.components.length);
|
||||
} else this.stats.push(0);
|
||||
} else {
|
||||
this.stats.push(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -36,14 +36,15 @@ module.exports = {
|
|||
|
||||
urls.forEach(function(u) {
|
||||
queue.push({
|
||||
"url": u,
|
||||
"wpt": wpt
|
||||
'url': u,
|
||||
'wpt': wpt
|
||||
}, function(data, err) {
|
||||
if (err) {
|
||||
log.log('error', 'Error running WebPageTest: ' + err);
|
||||
errors[u] = err;
|
||||
} else
|
||||
} else {
|
||||
pageData[u] = data;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -80,13 +81,13 @@ function analyzeUrl(args, asyncDoneCallback) {
|
|||
wpt.runTest(url, wptOptions, function(err, data) {
|
||||
|
||||
if (err) {
|
||||
log.log('error', "WebPageTest couldn't fetch info for url " + url + '(' +
|
||||
log.log('error', 'WebPageTest couldnt fetch info for url ' + url + '(' +
|
||||
JSON.stringify(err) + ')');
|
||||
asyncDoneCallback(undefined, err);
|
||||
return;
|
||||
}
|
||||
|
||||
var id = data.response.data.testId;
|
||||
// var id = data.response.data.testId;
|
||||
|
||||
/*
|
||||
console.log('Test id:' + data.response.data.testId);
|
||||
|
|
@ -107,7 +108,7 @@ function analyzeUrl(args, asyncDoneCallback) {
|
|||
});
|
||||
|
||||
wpt.getHARData(id, {}, function(err,data) {
|
||||
console.log("har:" + JSON.stringify(data));
|
||||
console.log('har:' + JSON.stringify(data));
|
||||
});
|
||||
*/
|
||||
|
||||
|
|
@ -118,11 +119,13 @@ function analyzeUrl(args, asyncDoneCallback) {
|
|||
|
||||
fs.writeFile(jsonPath, JSON.stringify(data), function(err) {
|
||||
if (err) {
|
||||
log.log('error', "WebPageTest couldn't store file for url " + url + '(' +
|
||||
log.log('error', 'WebPageTest couldnt store file for url ' + url + '(' +
|
||||
err + ')');
|
||||
asyncDoneCallback(undefined, err);
|
||||
|
||||
} else asyncDoneCallback(data, undefined);
|
||||
} else {
|
||||
asyncDoneCallback(data, undefined);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
90
lib/conf.js
90
lib/conf.js
|
|
@ -9,7 +9,7 @@ urlParser = require('url'),
|
|||
fs = require('fs-extra'),
|
||||
path = require('path'),
|
||||
supportedBrowsers = ['chrome','ie','firefox'],
|
||||
config = require("nomnom").options({
|
||||
config = require('nomnom').options({
|
||||
url: {
|
||||
abbr: 'u',
|
||||
metavar: '<URL>',
|
||||
|
|
@ -21,7 +21,7 @@ config = require("nomnom").options({
|
|||
help: 'The path to a plain text file with one URL on each row. Each line must end with a new line in the file.',
|
||||
callback: function(file) {
|
||||
if (!fs.existsSync(file))
|
||||
return "Couldn't find the file:" + file;
|
||||
return 'Could not find the file:' + file;
|
||||
}
|
||||
},
|
||||
sites: {
|
||||
|
|
@ -29,7 +29,7 @@ config = require("nomnom").options({
|
|||
help: 'The path to a plain text file with one URL on each row. Each line must end with a new line in the file.',
|
||||
callback: function(file) {
|
||||
if (!fs.existsSync(file))
|
||||
return "Couldn't find the file:" + file;
|
||||
return 'Couldnt find the file:' + file;
|
||||
}
|
||||
},
|
||||
version: {
|
||||
|
|
@ -37,7 +37,7 @@ config = require("nomnom").options({
|
|||
abbr: 'v',
|
||||
help: 'Display the sitespeed.io version',
|
||||
callback: function() {
|
||||
return require("../package.json").version;
|
||||
return require('../package.json').version;
|
||||
}
|
||||
},
|
||||
deep: {
|
||||
|
|
@ -46,8 +46,9 @@ config = require("nomnom").options({
|
|||
default: 1,
|
||||
help: 'How deep to crawl.',
|
||||
callback: function(deep) {
|
||||
if (deep != parseInt(deep))
|
||||
return "You must specify an integer";
|
||||
if (deep !== parseInt(deep)) {
|
||||
return 'You must specify an integer';
|
||||
}
|
||||
}
|
||||
},
|
||||
containInPath: {
|
||||
|
|
@ -66,10 +67,12 @@ config = require("nomnom").options({
|
|||
default: 5,
|
||||
help: 'The number of that will analyze pages.',
|
||||
callback: function(threads) {
|
||||
if (threads != parseInt(threads))
|
||||
return "You must specify an integer";
|
||||
else if (parseInt(threads) <= 0)
|
||||
return "You must specify a positive integer";
|
||||
if (threads !== parseInt(threads)) {
|
||||
return 'You must specify an integer';
|
||||
}
|
||||
else if (parseInt(threads) <= 0) {
|
||||
return 'You must specify a positive integer';
|
||||
}
|
||||
}
|
||||
},
|
||||
name: {
|
||||
|
|
@ -89,14 +92,16 @@ config = require("nomnom").options({
|
|||
callback: function(file) {
|
||||
if (!fs.existsSync(file)) {
|
||||
fs.mkdirs(file, function(err){
|
||||
if (err) return "Couldn't create the result base dir:" + err;
|
||||
if (err) {
|
||||
return 'Couldnt create the result base dir:' + err;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
userAgent: {
|
||||
metavar: '<USER-AGENT>',
|
||||
default: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36",
|
||||
default: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36',
|
||||
help: 'The full User Agent string, default is Chrome for MacOSX. You can also set the value as iphone or ipad (will automagically change the viewport)'
|
||||
},
|
||||
viewPort: {
|
||||
|
|
@ -110,8 +115,9 @@ config = require("nomnom").options({
|
|||
default: 'yslow-3.1.8-sitespeed.js',
|
||||
help: 'The compiled YSlow file.',
|
||||
callback: function(file) {
|
||||
if (!fs.existsSync(file))
|
||||
return "Couldn't find the file:" + fs.realpathSync(file);
|
||||
if (!fs.existsSync(file)) {
|
||||
return 'Couldnt find the file:' + fs.realpathSync(file);
|
||||
}
|
||||
}
|
||||
},
|
||||
ruleSet: {
|
||||
|
|
@ -133,13 +139,14 @@ config = require("nomnom").options({
|
|||
metavar: '<BROWSER>',
|
||||
help: 'Choose which browser to use to collect timing data. You can set multiple browsers in a comma separated list (firefox|chrome|ie)',
|
||||
callback: function(browsers) {
|
||||
b = browsers.split(","),
|
||||
var b = browsers.split(','),
|
||||
invalidBrowsers = b.filter(function(browser) {
|
||||
return supportedBrowsers.indexOf(browser) < 0;
|
||||
});
|
||||
|
||||
if (invalidBrowsers.length > 0)
|
||||
return "You specified a browser that is not supported:" + invalidBrowsers;
|
||||
if (invalidBrowsers.length > 0) {
|
||||
return 'You specified a browser that is not supported:' + invalidBrowsers;
|
||||
}
|
||||
}
|
||||
},
|
||||
profile: {
|
||||
|
|
@ -154,10 +161,10 @@ config = require("nomnom").options({
|
|||
default: 3,
|
||||
help: 'The number of times you should test each URL when fetching timing metrics. Default is three times',
|
||||
callback: function(n) {
|
||||
if (n != parseInt(n))
|
||||
return "You must specify an integer";
|
||||
if (n !== parseInt(n))
|
||||
return 'You must specify an integer';
|
||||
else if (parseInt(n) <= 0)
|
||||
return "You must specify a positive integer";
|
||||
return 'You must specify a positive integer';
|
||||
}
|
||||
},
|
||||
screenshot: {
|
||||
|
|
@ -175,15 +182,15 @@ config = require("nomnom").options({
|
|||
threshold: {
|
||||
default: 90,
|
||||
metavar: '[0-100]',
|
||||
help: "Threshold score for tests, will be used of no mathing thresholdFile with values match. Use : --threshold 95"
|
||||
help: 'Threshold score for tests, will be used of no mathing thresholdFile with values match. Use : --threshold 95'
|
||||
},
|
||||
thresholdFile: {
|
||||
metavar: '<FILE>',
|
||||
help: "A file containing JSON like {\"overall\": 90, \"thirdpartyversions\": 85}"
|
||||
help: 'A file containing JSON like {\'overall\': 90, \'thirdpartyversions\': 85}'
|
||||
},
|
||||
timingsThresholdFile: {
|
||||
metavar: '<FILE>',
|
||||
help: "A file containing JSON like ..."
|
||||
help: 'A file containing JSON like ...'
|
||||
},
|
||||
csv: {
|
||||
flag: true,
|
||||
|
|
@ -294,13 +301,13 @@ var startPath = (config.resultBaseDir.charAt(0) === path.sep) ? config.resultBas
|
|||
|
||||
if (config.url) {
|
||||
config.urlObject = urlParser.parse(config.url);
|
||||
config.run.absResultDir = path.join(startPath, config.urlObject.hostname, dateFormat(config.run.date, "yyyy-mm-dd-HH-MM-ss") );
|
||||
config.run.absResultDir = path.join(startPath, config.urlObject.hostname, dateFormat(config.run.date, 'yyyy-mm-dd-HH-MM-ss') );
|
||||
} else if (config.file) {
|
||||
// TODO handle the file name in a good way if it contains chars that will not fit in a dir
|
||||
config.run.absResultDir = path.join(startPath, config.file, dateFormat(config.run.date, "yyyy-mm-dd-HH-MM-ss") );
|
||||
config.run.absResultDir = path.join(startPath, config.file, dateFormat(config.run.date, 'yyyy-mm-dd-HH-MM-ss') );
|
||||
} else if (config.sites) {
|
||||
// The log file will end up here
|
||||
config.run.absResultDir = path.join(startPath, 'sites', dateFormat(config.run.date, "yyyy-mm-dd-HH-MM-ss"));
|
||||
config.run.absResultDir = path.join(startPath, 'sites', dateFormat(config.run.date, 'yyyy-mm-dd-HH-MM-ss'));
|
||||
}
|
||||
|
||||
// Parse the proxy info as a real URL
|
||||
|
|
@ -308,20 +315,22 @@ if (config.proxy) {
|
|||
config.urlProxyObject = urlParser.parse(config.proxy);
|
||||
}
|
||||
|
||||
if (config.thresholdFile)
|
||||
if (config.thresholdFile) {
|
||||
config.thresholds = require(config.thresholdFile);
|
||||
}
|
||||
|
||||
if (config.timingsThresholdFile)
|
||||
if (config.timingsThresholdFile) {
|
||||
config.timingThresholds = require(timingsThresholdFile);
|
||||
else
|
||||
}
|
||||
else {
|
||||
config.timingThresholds = require('../conf/junit-timings.json');
|
||||
|
||||
}
|
||||
// decide which rules to use ...
|
||||
if (config.profile === 'mobile') {
|
||||
config.rules= require('../conf/mobile-rules.json');
|
||||
config.ruleSet = "sitespeed.io-mobile";
|
||||
config.userAgent = "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25";
|
||||
config.viewPort = "320x444";
|
||||
config.ruleSet = 'sitespeed.io-mobile';
|
||||
config.userAgent = 'Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25';
|
||||
config.viewPort = '320x444';
|
||||
}
|
||||
else {
|
||||
config.rules= require(config.limitFile);
|
||||
|
|
@ -332,9 +341,9 @@ config.summaryBoxes = ['ruleScore'];
|
|||
|
||||
config.sitesColumns = ['requests','criticalPathScore','pageWeight','cacheTime','ruleScore'];
|
||||
|
||||
if (config.runYslow)
|
||||
config.pageColumns = ['yslow.assets.js','yslow.assets.css','yslow.assets.img','yslow.requests','rules.expiresmod.items','yslow.pageWeight', 'rules.avoidscalingimages.items','rules.criticalpath'];
|
||||
|
||||
if (config.runYslow) {
|
||||
config.pageColumns = ['yslow.assets.js','yslow.assets.css','yslow.assets.img','yslow.requests','rules.expiresmod.items','yslow.pageWeight', 'rules.avoidscalingimages.items','rules.criticalpath'];
|
||||
}
|
||||
if (config.columns) {
|
||||
config.pageColumns = config.columns[0].split(',');
|
||||
}
|
||||
|
|
@ -367,14 +376,17 @@ if (config.browser) {
|
|||
if (config.boxes) {
|
||||
if (config.boxes[0].indexOf('+')===0) {
|
||||
config.boxes[0].split(',').forEach(function (box) {
|
||||
if (box.indexOf('+')===0)
|
||||
if (box.indexOf('+')===0) {
|
||||
config.summaryBoxes.push(box.substring(1));
|
||||
else
|
||||
}
|
||||
else {
|
||||
config.summaryBoxes.push(box);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
else {
|
||||
config.summaryBoxes = config.boxes[0].split(',');
|
||||
}
|
||||
}
|
||||
|
||||
config.dataDir = 'data';
|
||||
|
|
|
|||
|
|
@ -62,8 +62,9 @@ module.exports.registerHelpers = function registerHelpers() {
|
|||
});
|
||||
|
||||
hb.registerHelper('isLowerThan', function(value, limit, options) {
|
||||
if (value < limit)
|
||||
if (value < limit) {
|
||||
return options.fn(this);
|
||||
}
|
||||
});
|
||||
|
||||
hb.registerHelper('getDecimals', function(value, decimals) {
|
||||
|
|
@ -83,9 +84,12 @@ module.exports.registerHelpers = function registerHelpers() {
|
|||
});
|
||||
|
||||
hb.registerHelper('getMatchingRuleName', function(id, rules) {
|
||||
if (rules.hasOwnProperty(id))
|
||||
if (rules.hasOwnProperty(id)) {
|
||||
return rules[id].name;
|
||||
else return id;
|
||||
}
|
||||
else {
|
||||
return id;
|
||||
}
|
||||
});
|
||||
|
||||
hb.registerHelper('prettyOSName', function(name) {
|
||||
|
|
@ -93,10 +97,12 @@ module.exports.registerHelpers = function registerHelpers() {
|
|||
// and windows has the following names, change them to
|
||||
// just Windows
|
||||
var windows = ['xp', 'windows', 'win8', 'win7'];
|
||||
if (windows.indexOf(name)>-1)
|
||||
if (windows.indexOf(name)>-1) {
|
||||
return 'Windows';
|
||||
else
|
||||
}
|
||||
else {
|
||||
return name.substr(0, 1).toUpperCase() + name.substr(1);
|
||||
}
|
||||
});
|
||||
|
||||
hb.registerHelper('capitalize', function(word) {
|
||||
|
|
@ -104,8 +110,9 @@ module.exports.registerHelpers = function registerHelpers() {
|
|||
});
|
||||
|
||||
hb.registerHelper('getPlural', function(value) {
|
||||
if (value>1)
|
||||
if (value>1) {
|
||||
return 's';
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
|
|
@ -139,23 +146,28 @@ module.exports.registerHelpers = function registerHelpers() {
|
|||
hb.registerHelper('getSiteAggregatedValue', function(siteName, type, metric, aggregates) {
|
||||
var value = '';
|
||||
aggregates[siteName].forEach(function (a) {
|
||||
if (a.id === metric)
|
||||
if (a.id === metric) {
|
||||
value = a.stats[type];
|
||||
}
|
||||
});
|
||||
return value;
|
||||
});
|
||||
|
||||
hb.registerHelper('getWPTWaterFall', function(run, whichView) {
|
||||
|
||||
// TypeError: Cannot read property 'images' of undefined
|
||||
if (Array.isArray(run))
|
||||
if (run[0][whichView])
|
||||
// TypeError: Cannot read property 'images' of undefined
|
||||
if (Array.isArray(run)) {
|
||||
if (run[0][whichView]) {
|
||||
return run[0][whichView].images.waterfall;
|
||||
else return;
|
||||
else
|
||||
if (run)
|
||||
return run[whichView].images.waterfall;
|
||||
else return;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else
|
||||
if (run) {
|
||||
return run[whichView].images.waterfall;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,11 +11,9 @@ var hb = require('handlebars'),
|
|||
config = require('./conf'),
|
||||
helpers = require('./hb-helpers'),
|
||||
columnsMetaData = require('../conf/columnsMetaData.json'),
|
||||
async = require("async"),
|
||||
async = require('async'),
|
||||
util = require('./util');
|
||||
|
||||
module.exports = HTMLRenderer;
|
||||
|
||||
var compiledTemplates = {},
|
||||
compiledPartials = {},
|
||||
ruleDictionary = {};
|
||||
|
|
@ -28,7 +26,9 @@ function HTMLRenderer() {
|
|||
|
||||
HTMLRenderer.prototype.copyAssets = function (toDir, cb) {
|
||||
fs.copy(path.join(__dirname, '../assets/'), toDir, function (err) {
|
||||
if (err) throw err;
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
cb();
|
||||
});
|
||||
};
|
||||
|
|
@ -39,19 +39,19 @@ HTMLRenderer.prototype.renderPage = function (url, pageData, cb) {
|
|||
var renderData = {};
|
||||
if (pageData.yslow) {
|
||||
renderData = {
|
||||
"url": pageData.yslow.originalUrl,
|
||||
"score": pageData.yslow.o,
|
||||
"size": util.getSize(pageData.yslow.comps),
|
||||
"rules": pageData.yslow.g,
|
||||
"assets": pageData.yslow.comps,
|
||||
"noOfDomains": util.getNumberOfDomains(pageData.yslow.comps),
|
||||
"timeSinceLastModificationStats": util.getLastModStats(pageData.yslow.comps),
|
||||
"cacheTimeStats": util.getCacheTimeStats(pageData.yslow.comps),
|
||||
"noOfAssetsThatIsCached": (pageData.yslow.comps.length - pageData.yslow.g.expiresmod.components.length),
|
||||
"assetsPerDomain": util.getAssetsPerDomain(pageData.yslow.comps),
|
||||
"assetsPerContentType": util.getAssetsPerContentType(pageData.yslow.comps),
|
||||
"sizePerContentType": util.getAssetsSizePerContentType(pageData.yslow.comps),
|
||||
"ruleDictionary": pageData.yslow.dictionary.rules,
|
||||
'url': pageData.yslow.originalUrl,
|
||||
'score': pageData.yslow.o,
|
||||
'size': util.getSize(pageData.yslow.comps),
|
||||
'rules': pageData.yslow.g,
|
||||
'assets': pageData.yslow.comps,
|
||||
'noOfDomains': util.getNumberOfDomains(pageData.yslow.comps),
|
||||
'timeSinceLastModificationStats': util.getLastModStats(pageData.yslow.comps),
|
||||
'cacheTimeStats': util.getCacheTimeStats(pageData.yslow.comps),
|
||||
'noOfAssetsThatIsCached': (pageData.yslow.comps.length - pageData.yslow.g.expiresmod.components.length),
|
||||
'assetsPerDomain': util.getAssetsPerDomain(pageData.yslow.comps),
|
||||
'assetsPerContentType': util.getAssetsPerContentType(pageData.yslow.comps),
|
||||
'sizePerContentType': util.getAssetsSizePerContentType(pageData.yslow.comps),
|
||||
'ruleDictionary': pageData.yslow.dictionary.rules,
|
||||
};
|
||||
}
|
||||
else {
|
||||
|
|
@ -63,9 +63,9 @@ HTMLRenderer.prototype.renderPage = function (url, pageData, cb) {
|
|||
renderData.wptData = pageData.webpagetest;
|
||||
renderData.config = config;
|
||||
renderData.pageMeta = {
|
||||
"path": "../",
|
||||
"title": "Page data, collected by sitespeed.io for page " + url,
|
||||
"description": "All data collected for this individual page."
|
||||
'path': '../',
|
||||
'title': 'Page data, collected by sitespeed.io for page ' + url,
|
||||
'description': 'All data collected for this individual page.'
|
||||
};
|
||||
var hash = util.getUrlHash(url);
|
||||
renderHtmlToFile('page', renderData, cb, hash + '.html', 'pages');
|
||||
|
|
@ -73,12 +73,12 @@ HTMLRenderer.prototype.renderPage = function (url, pageData, cb) {
|
|||
|
||||
HTMLRenderer.prototype.renderRules = function (cb) {
|
||||
var renderData = {
|
||||
"ruleDictionary": ruleDictionary,
|
||||
"config": config,
|
||||
"pageMeta": {
|
||||
"title": "The sitespeed.io rules used by this run",
|
||||
"description": "",
|
||||
"isRules": true
|
||||
'ruleDictionary': ruleDictionary,
|
||||
'config': config,
|
||||
'pageMeta': {
|
||||
'title': 'The sitespeed.io rules used by this run',
|
||||
'description': '',
|
||||
'isRules': true
|
||||
}
|
||||
};
|
||||
renderHtmlToFile('rules', renderData, cb);
|
||||
|
|
@ -91,8 +91,8 @@ HTMLRenderer.prototype.renderSites = function(sitesAggregates, cb) {
|
|||
// Add all sites data sorted
|
||||
Object.keys(sitesAggregates).forEach(function(site) {
|
||||
sitesAndAggregates.push({
|
||||
"site": site,
|
||||
"aggregates": sitesAggregates[site].filter(function(box) {
|
||||
'site': site,
|
||||
'aggregates': sitesAggregates[site].filter(function(box) {
|
||||
return (config.sitesColumns.indexOf(box.id) > -1);
|
||||
}).sort(function(box, box2) {
|
||||
return config.sitesColumns.indexOf(box.id) - config.sitesColumns.indexOf(box2.id);
|
||||
|
|
@ -100,16 +100,16 @@ HTMLRenderer.prototype.renderSites = function(sitesAggregates, cb) {
|
|||
});
|
||||
});
|
||||
var renderData = {
|
||||
"sitesAndAggregates": sitesAndAggregates,
|
||||
"columns": config.sitesColumns,
|
||||
"config": config,
|
||||
"columnsMeta": columnsMetaData,
|
||||
"ruleDictionary": ruleDictionary,
|
||||
"pageMeta": {
|
||||
"title": "",
|
||||
"description": "",
|
||||
"hideMenu": true,
|
||||
"isSites": true
|
||||
'sitesAndAggregates': sitesAndAggregates,
|
||||
'columns': config.sitesColumns,
|
||||
'config': config,
|
||||
'columnsMeta': columnsMetaData,
|
||||
'ruleDictionary': ruleDictionary,
|
||||
'pageMeta': {
|
||||
'title': '',
|
||||
'description': '',
|
||||
'hideMenu': true,
|
||||
'isSites': true
|
||||
}
|
||||
};
|
||||
renderHtmlToFile('sites', renderData, cb, 'sites.html', '..');
|
||||
|
|
@ -118,12 +118,12 @@ HTMLRenderer.prototype.renderSites = function(sitesAggregates, cb) {
|
|||
|
||||
HTMLRenderer.prototype.renderScreenshots = function (pages, cb) {
|
||||
var renderData = {
|
||||
"pages": pages,
|
||||
"config": config,
|
||||
"pageMeta": {
|
||||
"title": "",
|
||||
"description": "",
|
||||
"isScreenshots": true
|
||||
'pages': pages,
|
||||
'config': config,
|
||||
'pageMeta': {
|
||||
'title': '',
|
||||
'description': '',
|
||||
'isScreenshots': true
|
||||
}
|
||||
};
|
||||
renderHtmlToFile('screenshots', renderData, cb);
|
||||
|
|
@ -132,17 +132,17 @@ renderHtmlToFile('screenshots', renderData, cb);
|
|||
|
||||
HTMLRenderer.prototype.renderErrors = function (downloadErrors, analysisErrors, cb) {
|
||||
var renderData = {
|
||||
"errors": {
|
||||
"downloadErrorUrls": downloadErrors,
|
||||
"analysisErrorUrls": analysisErrors
|
||||
'errors': {
|
||||
'downloadErrorUrls': downloadErrors,
|
||||
'analysisErrorUrls': analysisErrors
|
||||
},
|
||||
"totalErrors": Object.keys(downloadErrors).length + Object.keys(analysisErrors).length ,
|
||||
"config": config,
|
||||
"numberOfPages":this.numberOfAnalyzedPages,
|
||||
"pageMeta": {
|
||||
"title": "Pages that couldn't be analyzed",
|
||||
"description": "Here are the pages that couldn't be analyzed by sitespeed.io",
|
||||
"isErrors": true
|
||||
'totalErrors': Object.keys(downloadErrors).length + Object.keys(analysisErrors).length ,
|
||||
'config': config,
|
||||
'numberOfPages':this.numberOfAnalyzedPages,
|
||||
'pageMeta': {
|
||||
'title': 'Pages that couldnt be analyzed',
|
||||
'description': 'Here are the pages that couldnt be analyzed by sitespeed.io',
|
||||
'isErrors': true
|
||||
}
|
||||
};
|
||||
renderHtmlToFile('errors', renderData, cb);
|
||||
|
|
@ -156,24 +156,24 @@ HTMLRenderer.prototype.renderSummary = function(aggregates, cb) {
|
|||
return config.summaryBoxes.indexOf(box.id) - config.summaryBoxes.indexOf(box2.id);
|
||||
});
|
||||
var summaryData = {
|
||||
"aggregates": filtered,
|
||||
"config": config,
|
||||
"numberOfPages": this.numberOfAnalyzedPages,
|
||||
"pageMeta": {
|
||||
"title": "Summary of the sitespeed.io result",
|
||||
"description": "A executive summary.",
|
||||
"isSummary": true
|
||||
'aggregates': filtered,
|
||||
'config': config,
|
||||
'numberOfPages': this.numberOfAnalyzedPages,
|
||||
'pageMeta': {
|
||||
'title': 'Summary of the sitespeed.io result',
|
||||
'description': 'A executive summary.',
|
||||
'isSummary': true
|
||||
}
|
||||
};
|
||||
|
||||
var detailedData = {
|
||||
"aggregates": aggregates,
|
||||
"config": config,
|
||||
"numberOfPages": this.numberOfAnalyzedPages,
|
||||
"pageMeta": {
|
||||
"title": "In details summary of the sitespeed.io result",
|
||||
"description": "The summary in details.",
|
||||
"isDetailedSummary": true
|
||||
'aggregates': aggregates,
|
||||
'config': config,
|
||||
'numberOfPages': this.numberOfAnalyzedPages,
|
||||
'pageMeta': {
|
||||
'title': 'In details summary of the sitespeed.io result',
|
||||
'description': 'The summary in details.',
|
||||
'isDetailedSummary': true
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -192,15 +192,15 @@ HTMLRenderer.prototype.renderSummary = function(aggregates, cb) {
|
|||
|
||||
HTMLRenderer.prototype.renderPages = function (pages, cb) {
|
||||
var renderData = {
|
||||
"pages": pages,
|
||||
"columnsMeta": columnsMetaData,
|
||||
"config": config,
|
||||
"ruleDictionary": ruleDictionary,
|
||||
"numberOfPages":this.numberOfAnalyzedPages,
|
||||
"pageMeta": {
|
||||
"title": "All pages information",
|
||||
"description": "All request data, for all the pages",
|
||||
"isPages": true
|
||||
'pages': pages,
|
||||
'columnsMeta': columnsMetaData,
|
||||
'config': config,
|
||||
'ruleDictionary': ruleDictionary,
|
||||
'numberOfPages':this.numberOfAnalyzedPages,
|
||||
'pageMeta': {
|
||||
'title': 'All pages information',
|
||||
'description': 'All request data, for all the pages',
|
||||
'isPages': true
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -212,42 +212,47 @@ HTMLRenderer.prototype.renderAssets = function (assets, cb) {
|
|||
return asset2.count - asset.count;
|
||||
});
|
||||
|
||||
if (sorted.length>200)
|
||||
if (sorted.length>200) {
|
||||
sorted.length = 200;
|
||||
}
|
||||
|
||||
var renderData = {
|
||||
"assets": sorted,
|
||||
"config": config,
|
||||
"numberOfPages":this.numberOfAnalyzedPages,
|
||||
"pageMeta": {
|
||||
"title": "The most used assets",
|
||||
"description": "A list of the most used assets for the analyzed pages.",
|
||||
"isAssets": true
|
||||
'assets': sorted,
|
||||
'config': config,
|
||||
'numberOfPages':this.numberOfAnalyzedPages,
|
||||
'pageMeta': {
|
||||
'title': 'The most used assets',
|
||||
'description': 'A list of the most used assets for the analyzed pages.',
|
||||
'isAssets': true
|
||||
}
|
||||
};
|
||||
renderHtmlToFile('assets', renderData, cb);
|
||||
};
|
||||
|
||||
function renderHtmlToFile(template, renderData, cb, fileName, optionalPath) {
|
||||
fileName = fileName || (template + ".html");
|
||||
fileName = fileName || (template + '.html');
|
||||
optionalPath = optionalPath || '';
|
||||
var result = compiledTemplates[template](renderData);
|
||||
var file = path.join(config.run.absResultDir, optionalPath, fileName);
|
||||
fs.outputFile(file, result, function(err) {
|
||||
if (err)
|
||||
log.log('error', "Couldn't write the file " + file + ' err:' + err);
|
||||
else
|
||||
log.log('info', "Wrote file " + fileName);
|
||||
if (err) {
|
||||
log.log('error', 'Couldnt write the file ' + file + ' err:' + err);
|
||||
}
|
||||
else {
|
||||
log.log('info', 'Wrote file ' + fileName);
|
||||
}
|
||||
cb();
|
||||
});
|
||||
}
|
||||
|
||||
function precompileTemplates() {
|
||||
compiledTemplates = compileTemplates(path.join(__dirname, "../templates/"));
|
||||
compiledPartials = compileTemplates(path.join(__dirname, "../templates/partials/"));
|
||||
compiledTemplates = compileTemplates(path.join(__dirname, '../templates/'));
|
||||
compiledPartials = compileTemplates(path.join(__dirname, '../templates/partials/'));
|
||||
|
||||
for (var key in compiledPartials) {
|
||||
if(compiledPartials.hasOwnProperty(key)) {
|
||||
hb.registerPartial(key, compiledPartials[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -255,8 +260,11 @@ function compileTemplates(folderPath) {
|
|||
// TODO would be cool to do this async
|
||||
var templates = {};
|
||||
fs.readdirSync(folderPath).forEach(function (file) {
|
||||
if (!fs.lstatSync(path.join(folderPath + file)).isDirectory())
|
||||
if (!fs.lstatSync(path.join(folderPath + file)).isDirectory()) {
|
||||
templates[path.basename(file, '.hb')] = hb.compile(fs.readFileSync(path.join(folderPath + file), 'utf8'));
|
||||
}
|
||||
});
|
||||
return templates;
|
||||
}
|
||||
|
||||
module.exports = HTMLRenderer;
|
||||
|
|
|
|||
158
lib/runner.js
158
lib/runner.js
|
|
@ -15,7 +15,7 @@ var crawler = require('./crawler'),
|
|||
dateFormat = require('dateformat'),
|
||||
fs = require('fs-extra'),
|
||||
config = require('./conf'),
|
||||
async = require("async"),
|
||||
async = require('async'),
|
||||
urlParser = require('url'),
|
||||
os = require('os'),
|
||||
EOL = os.EOL,
|
||||
|
|
@ -23,7 +23,7 @@ var crawler = require('./crawler'),
|
|||
childProcess = require('child_process'),
|
||||
log = require('winston');
|
||||
|
||||
module.exports = Runner;
|
||||
|
||||
|
||||
function Runner() {
|
||||
this.analyzer = new Analyzer();
|
||||
|
|
@ -51,11 +51,15 @@ Runner.prototype.run = function(finshedCb) {
|
|||
],
|
||||
|
||||
function(err, results){
|
||||
if (err) throw err;
|
||||
if (config.sites)
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
if (config.sites) {
|
||||
self._analyzeSites(finshedCb);
|
||||
else
|
||||
}
|
||||
else {
|
||||
self._analyzeSite(finshedCb);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -65,18 +69,22 @@ Runner.prototype._analyzeSites = function(cb) {
|
|||
// store all site data here, use it when parsing
|
||||
self.sites = {};
|
||||
|
||||
var urls = fs.readFile(config.sites, function(err, data) {
|
||||
if (err) throw err;
|
||||
fs.readFile(config.sites, function(err, data) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
var urls = data.toString().split(EOL);
|
||||
var queue = async.queue(self._setupConfigurationForSite, 1);
|
||||
log.log('info', 'Analyze ' + urls.length + ' sites');
|
||||
urls.forEach(function(url) {
|
||||
if (url !== "") queue.push({
|
||||
if (url !== '') {
|
||||
queue.push({
|
||||
'url': url,
|
||||
'runner': self
|
||||
}, function() {
|
||||
log.log('info', "Finished with site " + url);
|
||||
log.log('info', 'Finished with site ' + url);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
queue.drain = function() {
|
||||
|
|
@ -89,8 +97,9 @@ Runner.prototype._analyzeSites = function(cb) {
|
|||
}
|
||||
},
|
||||
function(err, results) {
|
||||
if (!err)
|
||||
log.log('info', "Wrote sites result to " + config.run.absResultDir);
|
||||
if (!err) {
|
||||
log.log('info', 'Wrote sites result to ' + config.run.absResultDir);
|
||||
}
|
||||
cb();
|
||||
});
|
||||
};
|
||||
|
|
@ -106,15 +115,17 @@ Runner.prototype._setupConfigurationForSite = function(args, cb) {
|
|||
config.resultBaseDir);
|
||||
|
||||
config.run.absResultDir = path.join(startPath, 'sites', dateFormat(config.run.date,
|
||||
"yyyy-mm-dd-HH-MM-ss"), config.urlObject.hostname);
|
||||
'yyyy-mm-dd-HH-MM-ss'), config.urlObject.hostname);
|
||||
// setup the directories needed
|
||||
var dataDir = path.join(config.run.absResultDir, config.dataDir);
|
||||
|
||||
fs.mkdirs(dataDir, function(err) {
|
||||
if (err) {
|
||||
log.log('error', "Couldn't create the data dir:" + dataDir + ' ' + err);
|
||||
log.log('error', 'Couldnt create the data dir:' + dataDir + ' ' + err);
|
||||
throw err;
|
||||
} else args.runner._analyzeSite(cb);
|
||||
} else {
|
||||
args.runner._analyzeSite(cb);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
|
@ -145,8 +156,9 @@ Runner.prototype._analyzeSite = function(cb) {
|
|||
self._createOutput(downloadErrors, analysisErrors, cb);
|
||||
}
|
||||
], function(err, result) {
|
||||
if (err)
|
||||
if (err) {
|
||||
log.log('error', err);
|
||||
}
|
||||
cb();
|
||||
});
|
||||
};
|
||||
|
|
@ -154,18 +166,19 @@ Runner.prototype._analyzeSite = function(cb) {
|
|||
Runner.prototype._fineTuneUrls = function (okUrls, errorUrls, callback) {
|
||||
var downloadErrors = {};
|
||||
Object.keys(errorUrls).forEach(function(url) {
|
||||
log.log('error', "Failed to download " + url);
|
||||
log.log('error', 'Failed to download ' + url);
|
||||
downloadErrors[url] = errorUrls[url];
|
||||
});
|
||||
|
||||
// limit
|
||||
if (config.maxPagesToTest) {
|
||||
if (okUrls.length > config.maxPagesToTest)
|
||||
if (okUrls.length > config.maxPagesToTest) {
|
||||
okUrls.length = config.maxPagesToTest;
|
||||
}
|
||||
}
|
||||
if (okUrls.length === 0) {
|
||||
log.log('info', "Didn't get any URLs");
|
||||
callback(new Error("No URLs to analyze"), okUrls, downloadErrors);
|
||||
log.log('info', 'Didnt get any URLs');
|
||||
callback(new Error('No URLs to analyze'), okUrls, downloadErrors);
|
||||
}
|
||||
else {
|
||||
saveUrls(okUrls);
|
||||
|
|
@ -175,14 +188,16 @@ Runner.prototype._fineTuneUrls = function (okUrls, errorUrls, callback) {
|
|||
|
||||
Runner.prototype._fetchUrls = function (crawler, callback) {
|
||||
if (config.url) {
|
||||
log.log('info', "Will crawl from start point " + config.url +
|
||||
" with crawl depth " + config.deep);
|
||||
log.log('info', 'Will crawl from start point ' + config.url +
|
||||
' with crawl depth ' + config.deep);
|
||||
crawler.crawl(config.url, function(okUrls, errorUrls) {
|
||||
callback(null, okUrls, errorUrls);
|
||||
});
|
||||
} else {
|
||||
fs.readFile(config.file, function (err, data) {
|
||||
if (err) throw err;
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
var urls = data.toString().split(EOL);
|
||||
urls = urls.filter(function(l) {
|
||||
return l.length > 0;
|
||||
|
|
@ -196,7 +211,7 @@ Runner.prototype._fetchUrls = function (crawler, callback) {
|
|||
Runner.prototype._analyze = function (urls, downloadErrors, callback) {
|
||||
var analysisErrors = {};
|
||||
var self = this;
|
||||
log.log('info', "Will analyze " + urls.length + " pages");
|
||||
log.log('info', 'Will analyze ' + urls.length + ' pages');
|
||||
this.analyzer.analyze(urls, this.collector, downloadErrors, analysisErrors, function(err, url, pageData) {
|
||||
|
||||
if (err) {
|
||||
|
|
@ -206,8 +221,9 @@ Runner.prototype._analyze = function (urls, downloadErrors, callback) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (config.junit)
|
||||
if (config.junit) {
|
||||
self.junitRenderer.renderForEachPage(url, pageData);
|
||||
}
|
||||
self.htmlRenderer.renderPage(url, pageData, function() {});
|
||||
}, callback);
|
||||
};
|
||||
|
|
@ -226,7 +242,9 @@ function createDataDir(cb) {
|
|||
// create the home data dir
|
||||
var dataDir = path.join(config.run.absResultDir, config.dataDir);
|
||||
fs.mkdirs(dataDir, function(err) {
|
||||
if (err) throw err;
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
cb(err, null);
|
||||
});
|
||||
}
|
||||
|
|
@ -236,48 +254,23 @@ function writeConfigurationFile(cb) {
|
|||
var confFile = path.join(config.run.absResultDir, 'config.json');
|
||||
fs.writeFile(confFile, JSON.stringify(
|
||||
config), function(err) {
|
||||
if (err) log.log('error',"Couldn't write configuration file to disk:"+ confFile + ' ' +err);
|
||||
if (err) {
|
||||
log.log('error','Couldnt write configuration file to disk:'+ confFile + ' ' +err);
|
||||
}
|
||||
cb(err, null);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function storeSummary(aggregates,cb) {
|
||||
var summary = path.join(config.run.absResultDir, config.dataDir, 'summary.json');
|
||||
fs.writeFile(summary, JSON.stringify(aggregates), function(err) {
|
||||
if(err) {
|
||||
log.log('error',"Couldn't write summary json file to disk:"+ summary + ' ' +err);
|
||||
log.log('error','Couldnt write summary json file to disk:'+ summary + ' ' +err);
|
||||
}
|
||||
cb();
|
||||
});
|
||||
}
|
||||
|
||||
function logVersions(cb) {
|
||||
|
||||
async.parallel([
|
||||
function(callback) {
|
||||
childProcess.execFile(binPath, ['--version'], {
|
||||
timeout: 120000
|
||||
}, function(err, stdout, stderr) {
|
||||
callback(null, stdout);
|
||||
});
|
||||
},
|
||||
function(callback) {
|
||||
childProcess.exec('java -version', {
|
||||
timeout: 120000
|
||||
}, function(err, stdout, stderr) {
|
||||
callback(null, stderr);
|
||||
});
|
||||
}
|
||||
],
|
||||
function(err, results) {
|
||||
log.log('info', 'OS: ' + os.platform() + ' ' + os.release() + ' sitespeed:' + require("../package.json").version +
|
||||
' ' + ' phantomJs:' + results[0].replace(EOL,'') + ' java:' + results[1].split(EOL)[0]);
|
||||
cb(null, null);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
Runner.prototype._createOutput = function (downloadErrors, analysisErrors, callBack) {
|
||||
log.log('info', 'Done analyzing urls');
|
||||
|
||||
|
|
@ -288,8 +281,9 @@ Runner.prototype._createOutput = function (downloadErrors, analysisErrors, callB
|
|||
|
||||
var self = this;
|
||||
|
||||
if (this.sites)
|
||||
if (this.sites) {
|
||||
this.sites[config.url] = aggregates;
|
||||
}
|
||||
|
||||
/* We got a lot of things to do, lets generate all results
|
||||
in parallel and then let us know when we are finished
|
||||
|
|
@ -320,17 +314,24 @@ Runner.prototype._createOutput = function (downloadErrors, analysisErrors, callB
|
|||
renderScreenshots: function(cb) {
|
||||
if (config.screenshot) {
|
||||
self.htmlRenderer.renderScreenshots(pages, cb);
|
||||
} else cb();
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
},
|
||||
sendToGraphite: function(cb) {
|
||||
if (config.graphiteHost)
|
||||
if (config.graphiteHost) {
|
||||
self.graphite.sendPageData(aggregates, pages, cb);
|
||||
else cb();
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
},
|
||||
renderJUnit: function(cb) {
|
||||
if (config.junit)
|
||||
if (config.junit) {
|
||||
self.junitRenderer.renderAfterFullAnalyse(cb);
|
||||
else cb();
|
||||
}
|
||||
else {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
},
|
||||
function(err, results) {
|
||||
|
|
@ -338,12 +339,41 @@ Runner.prototype._createOutput = function (downloadErrors, analysisErrors, callB
|
|||
// TODO this can be cleaner
|
||||
// We clear the number of pages tested and
|
||||
// the collected data, so it is ready for next run
|
||||
// used when testing multiple sites
|
||||
// used when testing multiple sites
|
||||
self.htmlRenderer.numberOfAnalyzedPages = 0;
|
||||
self.collector.clear();
|
||||
|
||||
if (!err)
|
||||
log.log('info', "Wrote results to " + config.run.absResultDir);
|
||||
if (!err) {
|
||||
log.log('info', 'Wrote results to ' + config.run.absResultDir);
|
||||
}
|
||||
callBack();
|
||||
});
|
||||
};
|
||||
|
||||
function logVersions(cb) {
|
||||
|
||||
async.parallel([
|
||||
function(callback) {
|
||||
childProcess.execFile(binPath, ['--version'], {
|
||||
timeout: 120000
|
||||
}, function(err, stdout, stderr) {
|
||||
callback(null, stdout);
|
||||
});
|
||||
},
|
||||
function(callback) {
|
||||
childProcess.exec('java -version', {
|
||||
timeout: 120000
|
||||
}, function(err, stdout, stderr) {
|
||||
callback(null, stderr);
|
||||
});
|
||||
}
|
||||
],
|
||||
function(err, results) {
|
||||
log.log('info', 'OS: ' + os.platform() + ' ' + os.release() + ' sitespeed:' + require('../package.json').version +
|
||||
' ' + ' phantomJs:' + results[0].replace(EOL,'') + ' java:' + results[1].split(EOL)[0]);
|
||||
cb(null, null);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
module.exports = Runner;
|
||||
|
|
|
|||
145
lib/util.js
145
lib/util.js
|
|
@ -28,8 +28,8 @@ module.exports = {
|
|||
|
||||
var response = comp.headers.response;
|
||||
for (var headerName in response) {
|
||||
if (! response.hasOwnProperty(headerName))
|
||||
continue;
|
||||
if (!response.hasOwnProperty(headerName))
|
||||
continue;
|
||||
|
||||
// Cache-control always wins before Expires
|
||||
// in the HTTP spec
|
||||
|
|
@ -99,8 +99,9 @@ module.exports = {
|
|||
var lastModifiedDate;
|
||||
var response = comp.headers.response;
|
||||
for (var headerName in response) {
|
||||
if (! response.hasOwnProperty(headerName))
|
||||
if (! response.hasOwnProperty(headerName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('last-modified' === headerName.toLowerCase()) {
|
||||
lastModifiedDate = new Date(response[headerName]);
|
||||
|
|
@ -110,8 +111,9 @@ module.exports = {
|
|||
}
|
||||
|
||||
// TODO how do we define this?
|
||||
if (!lastModifiedDate)
|
||||
if (!lastModifiedDate) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (now.getTime() - lastModifiedDate.getTime()) / 1000;
|
||||
},
|
||||
|
|
@ -123,34 +125,39 @@ module.exports = {
|
|||
*/
|
||||
prettyPrintSeconds: function(seconds) {
|
||||
|
||||
if (seconds === -1) return -1;
|
||||
if (seconds === -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var secondsPerYear = 365 * 24 * 60 * 60,
|
||||
secondsPerWeek = 60 * 60 * 24 * 7,
|
||||
secondsPerDay = 60 * 60 * 24,
|
||||
secondsPerHour = 60 * 60,
|
||||
secondsPerMinute = 60,
|
||||
sign = (seconds < 0) ? "-" : "";
|
||||
sign = (seconds < 0) ? '-' : '';
|
||||
|
||||
if (seconds < 0)
|
||||
if (seconds < 0) {
|
||||
seconds = Math.abs(seconds);
|
||||
}
|
||||
|
||||
if (seconds / secondsPerYear >= 1)
|
||||
return sign + Math.round(seconds / secondsPerYear) + " year" + ((Math.round(
|
||||
seconds / secondsPerYear) > 1) ? "s" : "");
|
||||
else if (seconds / secondsPerWeek >= 1)
|
||||
return sign + Math.round(seconds / secondsPerWeek) + " week" + ((Math.round(
|
||||
seconds / secondsPerWeek) > 1) ? "s" : "");
|
||||
else if (seconds / secondsPerDay >= 1)
|
||||
return sign + Math.round(seconds / secondsPerDay) + " day" + ((Math.round(
|
||||
seconds / secondsPerDay) > 1) ? "s" : "");
|
||||
else if (seconds / secondsPerHour >= 1)
|
||||
return sign + Math.round(seconds / secondsPerHour) + " hour" + ((Math.round(
|
||||
seconds / secondsPerHour) > 1) ? "s" : "");
|
||||
else if (seconds / secondsPerMinute >= 1)
|
||||
return sign + Math.round(seconds / secondsPerMinute) + " minute" + ((
|
||||
Math.round(seconds / secondsPerMinute) > 1) ? "s" : "");
|
||||
else return sign + seconds + " second" + ((seconds > 1 || seconds === 0) ? "s" : "");
|
||||
if (seconds / secondsPerYear >= 1) {
|
||||
return sign + Math.round(seconds / secondsPerYear) + ' year' + ((Math.round(
|
||||
seconds / secondsPerYear) > 1) ? 's' : '');
|
||||
} else if (seconds / secondsPerWeek >= 1) {
|
||||
return sign + Math.round(seconds / secondsPerWeek) + ' week' + ((Math.round(
|
||||
seconds / secondsPerWeek) > 1) ? 's' : '');
|
||||
} else if (seconds / secondsPerDay >= 1) {
|
||||
return sign + Math.round(seconds / secondsPerDay) + ' day' + ((Math.round(
|
||||
seconds / secondsPerDay) > 1) ? 's' : '');
|
||||
} else if (seconds / secondsPerHour >= 1) {
|
||||
return sign + Math.round(seconds / secondsPerHour) + ' hour' + ((Math.round(
|
||||
seconds / secondsPerHour) > 1) ? 's' : '');
|
||||
} else if (seconds / secondsPerMinute >= 1) {
|
||||
return sign + Math.round(seconds / secondsPerMinute) + ' minute' + ((
|
||||
Math.round(seconds / secondsPerMinute) > 1) ? 's' : '');
|
||||
} else {
|
||||
return sign + seconds + ' second' + ((seconds > 1 || seconds === 0) ? 's' : '');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -159,13 +166,18 @@ module.exports = {
|
|||
* add ms to milliseconds and turn bytes into kiloytes.
|
||||
*/
|
||||
getHumanReadable: function(data, value, showUnit) {
|
||||
if (data.unit === 'seconds')
|
||||
if (data.unit === 'seconds') {
|
||||
return this.prettyPrintSeconds(value);
|
||||
else if (data.unit === 'milliseconds')
|
||||
}
|
||||
else if (data.unit === 'milliseconds') {
|
||||
return value + (showUnit ? ' ms':'');
|
||||
else if (data.unit === 'bytes')
|
||||
}
|
||||
else if (data.unit === 'bytes') {
|
||||
return this.getKbSize(value, showUnit);
|
||||
else return value;
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -176,17 +188,21 @@ module.exports = {
|
|||
if (config.rules[rule]) {
|
||||
var diff = config.rules[rule].warning - config.rules[rule].error;
|
||||
if (diff > 0) {
|
||||
if (value>config.rules[rule].warning)
|
||||
if (value>config.rules[rule].warning) {
|
||||
return 'success';
|
||||
else if (value>config.rules[rule].error)
|
||||
}
|
||||
else if (value>config.rules[rule].error) {
|
||||
return 'warning';
|
||||
}
|
||||
return 'danger';
|
||||
}
|
||||
else {
|
||||
if (value<config.rules[rule].warning)
|
||||
if (value<config.rules[rule].warning) {
|
||||
return 'success';
|
||||
else if (value<config.rules[rule].error)
|
||||
}
|
||||
else if (value<config.rules[rule].error) {
|
||||
return 'warning';
|
||||
}
|
||||
return 'danger';
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +216,7 @@ module.exports = {
|
|||
**/
|
||||
getSize: function(components) {
|
||||
return components.filter(function(comp) {
|
||||
return comp.size != '-1';
|
||||
return comp.size !== '-1';
|
||||
}).reduce(function(sum, comp) {
|
||||
return sum + comp.size;
|
||||
}, 0);
|
||||
|
|
@ -212,11 +228,12 @@ module.exports = {
|
|||
*/
|
||||
getKbSize: function(size, showUnit) {
|
||||
// if we don't have any values in the stats
|
||||
if (isNaN(size))
|
||||
if (isNaN(size)) {
|
||||
return 0 + ' kb';
|
||||
}
|
||||
var remainder = size % (size > 100 ? 100 : 10);
|
||||
size -= remainder;
|
||||
return parseFloat(size / 1000) + (0 === (size % 1000) ? ".0" : "") + (showUnit?' kb':'');
|
||||
return parseFloat(size / 1000) + (0 === (size % 1000) ? '.0' : '') + (showUnit?' kb':'');
|
||||
},
|
||||
|
||||
select: function(object, keyPath, defaultValue) {
|
||||
|
|
@ -241,7 +258,7 @@ module.exports = {
|
|||
var urlComponents = url.parse(u);
|
||||
var hash = crypto.createHash('md5').update(u).digest('hex').substr(0, 7);
|
||||
var name = urlComponents.pathname;
|
||||
if (name == '/') {
|
||||
if (name === '/') {
|
||||
name = urlComponents.hostname;
|
||||
} else {
|
||||
name = name.replace(/^\/|\/$/g, '').split('/').pop();
|
||||
|
|
@ -294,17 +311,17 @@ module.exports = {
|
|||
|
||||
|
||||
timingMetricsDefinition: {
|
||||
"firstPaintTime": "This is when the first paint happens on the screen, reported by the browser.",
|
||||
"serverConnectionTime": 'How long time it takes to connect to the server. Definition: connectEnd - connectStart',
|
||||
"domainLookupTime": 'The time it takes to do the DNS lookup. Definition: domainLookupEnd - domainLookupStart',
|
||||
"pageLoadTime": 'The time it takes for page to load, from initiation of the pageview (e.g., click on a page link) to load completion in the browser. Important: this is only relevant to some pages, depending on how you page is built. Definition: loadEventStart - navigationStart',
|
||||
"pageDownloadTime":'How long time does it take to download the page (the HTML). Definition: responseEnd - responseStart',
|
||||
"serverResponseTime": 'How long time does it take until the server respond. Definition: responseStart - requestStart',
|
||||
"domContentLoadedTime": "The time the browser takes to parse the document and execute deferred and parser-inserted scripts including the network time from the user's location to your server. Definition: domContentLoadedEventStart - navigationStart",
|
||||
"domInteractiveTime": "The time the browser takes to parse the document, including the network time from the user's location to your server. Definition: domInteractive - navigationStart",
|
||||
"redirectionTime": "Time spent on redirects. Definition: fetchStart - navigationStart",
|
||||
"backEndTime": 'The time it takes for the network and the server to generate and start sending the HTML. Definition: responseStart - navigationStart',
|
||||
"frontEndTime": 'The time it takes for the browser to parse and create the page. Definition: loadEventStart - responseEnd'
|
||||
'firstPaintTime': 'This is when the first paint happens on the screen, reported by the browser.',
|
||||
'serverConnectionTime': 'How long time it takes to connect to the server. Definition: connectEnd - connectStart',
|
||||
'domainLookupTime': 'The time it takes to do the DNS lookup. Definition: domainLookupEnd - domainLookupStart',
|
||||
'pageLoadTime': 'The time it takes for page to load, from initiation of the pageview (e.g., click on a page link) to load completion in the browser. Important: this is only relevant to some pages, depending on how you page is built. Definition: loadEventStart - navigationStart',
|
||||
'pageDownloadTime':'How long time does it take to download the page (the HTML). Definition: responseEnd - responseStart',
|
||||
'serverResponseTime': 'How long time does it take until the server respond. Definition: responseStart - requestStart',
|
||||
'domContentLoadedTime': 'The time the browser takes to parse the document and execute deferred and parser-inserted scripts including the network time from the users location to your server. Definition: domContentLoadedEventStart - navigationStart',
|
||||
'domInteractiveTime': 'The time the browser takes to parse the document, including the network time from the users location to your server. Definition: domInteractive - navigationStart',
|
||||
'redirectionTime': 'Time spent on redirects. Definition: fetchStart - navigationStart',
|
||||
'backEndTime': 'The time it takes for the network and the server to generate and start sending the HTML. Definition: responseStart - navigationStart',
|
||||
'frontEndTime': 'The time it takes for the browser to parse and create the page. Definition: loadEventStart - responseEnd'
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -385,43 +402,57 @@ module.exports = {
|
|||
} else if (args.length === 3) {
|
||||
return text.replace('$1', args[0].value).replace('$2', args[1].value).replace(
|
||||
'$3', args[2].value);
|
||||
} else return text;
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the URL from pageData.
|
||||
*/
|
||||
getURLFromPageData: function(pageData) {
|
||||
if (pageData.yslow)
|
||||
if (pageData.yslow) {
|
||||
return pageData.yslow.originalUrl;
|
||||
else if (pageData.browsertime)
|
||||
}
|
||||
else if (pageData.browsertime) {
|
||||
return pageData.browsertime[0].pageData.url;
|
||||
else if (pageData.gpsi)
|
||||
}
|
||||
else if (pageData.gpsi) {
|
||||
return pageData.gpsi.id;
|
||||
else if (pageData.webpagetest)
|
||||
}
|
||||
else if (pageData.webpagetest) {
|
||||
return pageData.webpagetest.response.data.testUrl;
|
||||
}
|
||||
return 'undefined';
|
||||
},
|
||||
|
||||
getGraphiteURLKey: function(theUrl) {
|
||||
myUrl = url.parse(theUrl);
|
||||
var myUrl = url.parse(theUrl);
|
||||
var protocol = myUrl.protocol.replace(':', '');
|
||||
var hostname = myUrl.hostname;
|
||||
var path = myUrl.pathname;
|
||||
|
||||
|
||||
if (path.indexOf(".") > -1) path = path.replace(".", "_");
|
||||
if (path.indexOf("~") > -1) path = path.replace("~", "_");
|
||||
if (path.indexOf('.') > -1) {
|
||||
path = path.replace('.', '_');
|
||||
}
|
||||
if (path.indexOf('~') > -1) {
|
||||
path = path.replace('~', '_');
|
||||
}
|
||||
|
||||
|
||||
if (path === '' || path === '/')
|
||||
if (path === '' || path === '/') {
|
||||
return protocol + '.' + hostname + '.slash.';
|
||||
}
|
||||
|
||||
|
||||
var key = protocol + '.' + hostname + '.' + path.replace('/', '.');
|
||||
if (key.indexOf('.', key.length - 1) !== -1)
|
||||
if (key.indexOf('.', key.length - 1) !== -1) {
|
||||
return key;
|
||||
else return key + '.';
|
||||
}
|
||||
else {
|
||||
return key + '.';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue