lighthouse-multi
Version:
lighthouse wrapper that runs x number of audits against a list of endpoints
149 lines (148 loc) • 5.61 kB
JavaScript
const chromeLauncher = require('chrome-launcher');
const fs = require('fs');
const lighthouse = require('lighthouse');
const lighthouseKeys = require('./lighthouseKeys.json');
const log = require('lighthouse-logger');
const yargs = require('yargs');
const options = yargs
.usage('Usage: --depth <depth> --disableStorageReset <disableStorageReset> --endpoints <endpoints> --extraHeaders <extraHeaders> --output <output>')
.option('depth', {
describe: 'number of lighthouse audits per endpoint',
type: 'number',
})
.option('disableStorageReset', {
describe: 'allow stored browser credentials to persist',
type: 'boolean',
})
.option('endpoints', {
describe: 'comma-separated list of endpoints',
type: 'string',
demandOption: true,
})
.option('extraHeaders', {
describe: 'comma-separated list of key-value headers',
type: 'string',
})
.option('output', {
describe: 'destination folder for the generated report',
type: 'string',
})
.argv;
const { depth = 1, disableStorageReset = false, endpoints, extraHeaders = '', output = 'reports', } = options;
if (!fs.existsSync(`./${output}`))
fs.mkdirSync(`./${output}`);
const hyphenateString = (str) => str.replace(/(\/|\s|:|\.)/g, '-')
.replace(',', '')
.replace(/-{2,}/g, '-')
.replace(/-$/, '');
const runLighthouse = async (name, url, opts, config) => {
const chrome = await chromeLauncher.launch({ chromeFlags: ['--ignore-certificate-errors'] });
opts.port = chrome.port;
const results = await lighthouse(url, opts, config);
await chrome.kill();
const filename = `${hyphenateString(`${name}-${new Date().toLocaleString()}`)}.json`;
await fs.writeFileSync(`./${output}/${filename}`, results.report);
};
const flags = {
logLevel: 'info',
};
log.setLevel(flags.logLevel);
let headers = '';
if (extraHeaders) {
headers = extraHeaders.split(',').map((item) => {
const [name, value] = item.split('=');
return { [name]: value.replace(/["']/g, '') };
});
}
const config = {
extends: 'lighthouse:default',
settings: {
disableStorageReset,
emulatedUserAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4143.7 Safari/537.36 Chrome-Lighthouse',
extraHeaders: headers,
formFactor: 'desktop',
onlyCategories: ['performance'],
screenEmulation: {
mobile: false,
width: 1350,
height: 940,
deviceScaleFactor: 1,
disabled: false,
},
throttling: {
rttMs: 40,
throughputKbps: 10 * 1024,
cpuSlowdownMultiplier: 1,
requestLatencyMs: 0,
downloadThroughputKbps: 0,
uploadThroughputKbps: 0,
}
},
};
const runLighthousePerEndpoint = async (endpoints) => {
const endpointArr = endpoints.split(',');
const namePair = {};
console.log('\nInitializing...\n');
for (let index = 0; index < depth; index++) {
for (const endpoint of endpointArr) {
const name = hyphenateString(endpoint);
namePair[name] = endpoint;
await runLighthouse(name, endpoint, flags, config);
console.log(`\n\x1b[37mPass ${index + 1} of \x1b[32m${endpoint} \x1b[37mfinished.\n`);
}
}
generateReport(namePair);
};
const generateReport = async (names) => {
const { diagnosticKeys, numericValueKeys } = lighthouseKeys;
const metrics = {};
const report = {};
const nameList = {};
const files = await fs.readdirSync(`./${output}`);
for (const name in names) {
nameList[name] = [];
}
const getAverage = (arr) => arr.reduce((acc, curr) => acc + curr, 0) / arr.length;
for (const name in nameList) {
metrics[name] = {};
for (const file of files) {
if (file.includes(name))
nameList[name].push(file);
}
for (const fileName of nameList[name]) {
const contents = await JSON.parse(fs.readFileSync(`./${output}/${fileName}`, 'utf8'));
for (const metric in diagnosticKeys) {
if (!metrics[name][metric])
metrics[name][metric] = [];
metrics[name][metric].push(contents.audits.diagnostics.details.items[0][metric]);
}
;
for (const metric in numericValueKeys) {
if (!metrics[name][metric])
metrics[name][metric] = [];
metrics[name][metric].push(contents.audits[metric].numericValue);
}
;
}
report[name] = {};
console.log(`\n\x1b[33m${names[name]}\x1b[37m\n`);
for (const [key, value] of Object.entries(numericValueKeys)) {
report[name][key] = getAverage(metrics[name][key]);
console.log(`> ${value}: \x1b[32m${getAverage(metrics[name][key])}\x1b[37m`);
}
for (const [key, value] of Object.entries(diagnosticKeys)) {
report[name][key] = getAverage(metrics[name][key]);
console.log(`> ${value}: \x1b[32m${getAverage(metrics[name][key])}\x1b[37m`);
}
}
;
const filename = `${hyphenateString(`report-${new Date().toLocaleString()}`)}.json`;
fs.writeFile(`./${output}/${filename}`, JSON.stringify(report), (err) => {
if (err)
throw err;
console.log(`\n\x1b[37mReport written in ./${output} as file: \x1b[36m${filename}\n`);
});
};
runLighthousePerEndpoint(endpoints);
;