diff --git a/index.js b/index.js index ca5933c..79ba7c7 100755 --- a/index.js +++ b/index.js @@ -1,84 +1,14 @@ #!/usr/bin/env node -const lighthouse = require('lighthouse'), - chromeLauncher = require('chrome-launcher'), - queue = require('async/queue'), - cTable = require('console.table'), - loadingSpinner = require('loading-spinner'), - program = require('commander'), - packageJson = require('./package.json'); +const validate = require('./src/validate'), + params = require('./src/params'); -var allResults = [[],[]]; -var config = { - instances: 5, - iterations: 5 -} - -function launchChromeAndRunLighthouse(url, config = null) { - const opts = {chromeFlags: ['--headless']}; - return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => { - opts.port = chrome.port; - return lighthouse(url, opts, config).then(results => { - return chrome.kill().then(() => results.lhr) - }); - }); -} - -function toTitleCase(str) { - return str.replace(/-/g, ' ').replace(/\w\S*/g, function(txt){ - return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); - }); -} - -function begin(url1, url2){ - loadingSpinner.start(100, { clearChar: true, doNotBlock: true }); - - config.iterations = program.number || number; - config.instances = program.instances || instances; +var config = params(); - const lighthouseQueue = queue((endpoint, callback) => { - launchChromeAndRunLighthouse(endpoint.url).then(function(results) { - allResults[endpoint.version].push(results); - callback() - }); - }, config.instances) +if(validate(config)){ + const lightdiff = require('./src/lightdiff'); - lighthouseQueue.drain = function() { - loadingSpinner.stop(); + console.log(config) - var table = [], arr = ['first-meaningful-paint', 'first-contentful-paint', 'speed-index', 'estimated-input-latency', 'time-to-first-byte', - 'first-cpu-idle', 'interactive', 'mainthread-work-breakdown', 'bootup-time', 'network-requests', 'total-byte-weight', 'unused-css-rules']; - - arr.forEach( function(string) { - var before = Math.round(allResults[0].reduce((a,c) => (c['audits'][string]['rawValue'] + a), 0) / allResults[0].length); - var after = Math.round(allResults[1].reduce((a,c) => (c['audits'][string]['rawValue'] + a), 0) / allResults[0].length); - var difference = -((before - after) / before * 100).toFixed(2); - var tableData = {}; - - tableData["Metric"] = toTitleCase(string); - tableData['Url 1'] = before; - tableData['Url 2'] = after; - tableData["Difference"] = difference > 0 ? '+' + difference + '%' : difference + '%'; - - table.push(tableData); - }); - - console.log('\n'); - console.table(table); - }; - - for(var x = 0; x < config.iterations; x++){ - lighthouseQueue.push({url: url1, version: 0}) - lighthouseQueue.push({url: url2, version: 1}) - } + lightdiff(config); } - -program - .version(packageJson.version) - .arguments(' ') - .option('-n, --number ', 'The number of times both URL\'s should be run in lighthouse (default: 5)') - .option('-o, --one ', 'The title of the first URL tested') - .option('-t, --two ', 'The title of the second URL tested') - .option('-i, --instances ', 'The number lighthouse instances used at once (default: 5)') - .action(begin) - .parse(process.argv); diff --git a/package.json b/package.json index d6db3c3..fa2c061 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,9 @@ "version": "1.0.4", "description": "Command line tool for comparing the average performance of two urls.", "main": "index.js", + "engines": { + "node": ">=8.9" + }, "bin": { "lightdiff": "./index.js" }, @@ -21,7 +24,8 @@ "commander": "^2.16.0", "console.table": "^0.10.0", "lighthouse": "^3.0.2", - "loading-spinner": "^1.2.0" + "loading-spinner": "^1.2.0", + "semver": "^5.5.0" }, "keywords": [ "compare", diff --git a/src/helpers/dashToTitleCase.js b/src/helpers/dashToTitleCase.js new file mode 100644 index 0000000..572d0f8 --- /dev/null +++ b/src/helpers/dashToTitleCase.js @@ -0,0 +1,5 @@ +module.exports = function (str) { + return str.replace(/-/g, ' ').replace(/\w\S*/g, function(txt){ + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }); +} \ No newline at end of file diff --git a/src/lightdiff.js b/src/lightdiff.js new file mode 100644 index 0000000..ba42daa --- /dev/null +++ b/src/lightdiff.js @@ -0,0 +1,66 @@ +const lighthouse = require('lighthouse'), + chromeLauncher = require('chrome-launcher'), + queue = require('async/queue'), + cTable = require('console.table'), + loadingSpinner = require('loading-spinner'), + dashToTitleCase = require('./helpers/dashToTitleCase'); + +var allResults = [[],[]]; +var runningConfig = {}; + +function launchChromeAndRunLighthouse(url, config = null) { + console.log(url); + + + const opts = {chromeFlags: ['--headless']}; + return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => { + opts.port = chrome.port; + return lighthouse(url, opts, config).then(results => { + return chrome.kill().then(() => results.lhr) + }); + }); +} + +module.exports = function (config){ + loadingSpinner.start(100, { clearChar: true, doNotBlock: true }); + + runningConfig = config; + + const lighthouseQueue = queue((endpoint, callback) => { + launchChromeAndRunLighthouse(endpoint.url).then(function(results) { + allResults[endpoint.version].push(results); + callback() + }); + }, config.instances) + + lighthouseQueue.drain = function() { + console.log('heheheh'); + + loadingSpinner.stop(); + + var table = [], arr = ['first-meaningful-paint', 'first-contentful-paint', 'speed-index', 'estimated-input-latency', 'time-to-first-byte', + 'first-cpu-idle', 'interactive', 'mainthread-work-breakdown', 'bootup-time', 'network-requests', 'total-byte-weight', 'unused-css-rules']; + + arr.forEach( function(string) { + var before = Math.round(allResults[0].reduce((a,c) => (c['audits'][string]['rawValue'] + a), 0) / allResults[0].length); + var after = Math.round(allResults[1].reduce((a,c) => (c['audits'][string]['rawValue'] + a), 0) / allResults[0].length); + var difference = -((before - after) / before * 100).toFixed(2); + var tableData = {}; + + tableData["Metric"] = dashToTitleCase(string); + tableData['Url 1'] = before; + tableData['Url 2'] = after; + tableData["Difference"] = difference > 0 ? '+' + difference + '%' : difference + '%'; + + table.push(tableData); + }); + + console.log('\n'); + console.table(table); + }; + + for(var x = 0; x < config.iterations; x++){ + lighthouseQueue.push({url: config.url1, version: 0}) + lighthouseQueue.push({url: config.url2, version: 1}) + } +} diff --git a/src/params.js b/src/params.js new file mode 100644 index 0000000..0b8616f --- /dev/null +++ b/src/params.js @@ -0,0 +1,24 @@ +const program = require('commander'), + packageJson = require('../package.json'); + +module.exports = function() { + var config = {}; + + program + .version(packageJson.version) + .arguments(' ') + .option('-n, --number ', 'The number of times both URL\'s should be run in lighthouse (default: 5)') + .option('-o, --one ', 'The title of the first URL tested') + .option('-t, --two ', 'The title of the second URL tested') + .option('-i, --instances ', 'The number lighthouse instances used at once (default: 5)') + .action(function (url1, url2) { + config.url1 = url1; + config.url2 = url2; + }) + .parse(process.argv); + + config.instances = program.instances || 5; + config.iterations = program.number || 5; + + return config; +} \ No newline at end of file diff --git a/src/validate.js b/src/validate.js new file mode 100644 index 0000000..9c1a479 --- /dev/null +++ b/src/validate.js @@ -0,0 +1,37 @@ +const packageJson = require('../package.json'), + semver = require('semver'); + +module.exports = function(config){ + var safe = true; + const number = config.number, + iterations = config.iterations, + version = packageJson.engines.node; + + if (!semver.satisfies(process.version, version)) { + console.log(`Required node version ${version} not satisfied with current version ${process.version}.`); + safe = false; + } + + if(!config.url1 || config.url1 == '' && !config.url2 || config.url2 == ''){ + console.error('Error: url1 & url2 must be provided!'); + safe = false; + }else if(!config.url1 || config.url1 == ''){ + console.error('Error: url1 must be provided!'); + safe = false; + }else if(!config.url2 || config.url2 == ''){ + console.error('Error: url2 must be provided!'); + safe = false; + } + + if(number && !/^\d+$/.test(number)){ + console.error('Error: number value must be a number!'); + safe = false; + } + + if(iterations && !/^\d+$/.test(iterations)){ + console.error('Error: iterations value must be a number!'); + safe = false; + } + + return safe; +} \ No newline at end of file