UNPKG

lighthouse-multi

Version:

lighthouse wrapper that runs x number of audits against a list of endpoints

149 lines (148 loc) 5.61 kB
#! /usr/bin/env node "use strict"; 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);