Skip to content

Instantly share code, notes, and snippets.

@WebDevLuke

WebDevLuke/lh.js Secret

Last active September 20, 2023 20:57
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save WebDevLuke/cb8ad1ce9cba72c4f25f8d35d4bbba5a to your computer and use it in GitHub Desktop.
Save WebDevLuke/cb8ad1ce9cba72c4f25f8d35d4bbba5a to your computer and use it in GitHub Desktop.
Simple Google Lighthouse tool to create and compare reports from the console.
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
const argv = require('yargs').argv;
const url = require('url');
const fs = require('fs');
const glob = require('glob');
const path = require('path');
const launchChromeAndRunLighthouse = (url) => {
return chromeLauncher.launch().then(chrome => {
const opts = {
port: chrome.port
}
return lighthouse(url, opts).then(results => {
return chrome.kill().then(() => {
return {
js: results.lhr,
json: results.report
}
});
});
});
}
const getContents = (pathStr) => {
const output = fs.readFileSync(pathStr, 'utf8', (err, results) => {
return results;
});
return JSON.parse(output);
};
const compareReports = (from, to) => {
const metricFilter = [
'first-contentful-paint',
'first-meaningful-paint',
'speed-index',
'estimated-input-latency',
'total-blocking-time',
'max-potential-fid',
'time-to-first-byte',
'first-cpu-idle',
'interactive'
]
const calcPercentageDiff = (from, to) => {
const per = ((to - from) / from) * 100;
return Math.round(per * 100) / 100;
};
for(let auditObj in from['audits']) {
if(metricFilter.includes(auditObj)) {
const percentageDiff = calcPercentageDiff(
from['audits'][auditObj].numericValue,
to['audits'][auditObj].numericValue
);
let logColor = '\x1b[37m';
const log = (() => {
if(Math.sign(percentageDiff) === 1) {
logColor = "\x1b[31m";
return `${percentageDiff.toString().replace('-','') + '%'} slower`;
}
else if(Math.sign(percentageDiff) === 0) {
return 'unchanged';
}
else {
logColor = "\x1b[32m";
return `${percentageDiff.toString().replace('-','') + '%'} faster`;
}
})();
console.log(logColor, `${from['audits'][auditObj].title} is ${log}`);
}
}
}
if(argv.from && argv.to) {
compareReports(
getContents(argv.from + '.json'),
getContents(argv.to + '.json')
);
}
else if(argv.url) {
const urlObj = new URL(argv.url);
let dirName = urlObj.host.replace('www.','');
if(urlObj.pathname !== '/') {
dirName = dirName + urlObj.pathname.replace(/\//g,'_');
}
if(!fs.existsSync(dirName)) {
fs.mkdirSync(dirName);
}
launchChromeAndRunLighthouse(argv.url).then(results => {
const prevReports = glob(`${dirName}/*.json`, {
sync: true
});
if(prevReports.length) {
dates = [];
for(report in prevReports) {
dates.push(new Date(path.parse(prevReports[report]).name.replace(/_/g, ':')));
}
const max = dates.reduce(function(a, b) {
return Math.max(a, b);
});
const recentReport = new Date(max).toISOString();
const recentReportContents = getContents(dirName + '/' + recentReport.replace(/:/g, '_') + '.json');
compareReports(recentReportContents, results.js);
}
fs.writeFile(`${dirName}/${results.js['fetchTime'].replace(/:/g, '_')}.json`, results.json, (err) => {
if (err) throw err;
});
});
}
else {
throw "You haven't passed a URL to Lighthouse";
}
@kanagas3
Copy link

can we have the same working with Chromium as a CLI ?

@WebDevLuke
Copy link
Author

can we have the same working with Chromium as a CLI ?

Like a headless browser?

@kanagas3
Copy link

can we have the same working with Chromium as a CLI ?

Like a headless browser?
yes similar like headless... i'm using lighthouse-ci and looking for some solution which compares the reports on every run

@nguyenduonghai-sky
Copy link

Hi there, if my test web has a popup require you to input authentication(username,password) before you can access to the page, what should I do? Any help would be very appreciated. Thank you!

@devzom
Copy link

devzom commented Nov 18, 2022

@nguyenduonghai-sky You need to use some automation script to pass the authentication, You can use puppeter, cherrio or soo.

Check ex: puppeter example
but also there is lighthouse docs:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment