Skip to content

Instantly share code, notes, and snippets.

@SilentImp SilentImp/avarage.js
Last active Apr 12, 2020

Embed
What would you like to do?
const fs = require('fs');
const lighthouse = require('lighthouse');
const puppeteer = require('puppeteer');
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
const DOMAIN = process.env.DOMAIN;
// Count of measurements we want to make
const MEASURES_COUNT = 3;
// build report for single url
const buildReport = browser => async url => {
const data = await lighthouse(
`${DOMAIN}${url}`,
{
port: new URL(browser.wsEndpoint()).port,
output: 'json',
},
{
extends: 'lighthouse:full',
}
);
const { report: reportJSON } = data;
const report = JSON.parse(reportJSON);
const metrics = [
{
name: report.categories.performance.title,
value: report.categories.performance.score,
desiredSize: 'larger',
},
{
name: report.categories.accessibility.title,
value: report.categories.accessibility.score,
desiredSize: 'larger',
},
{
name: report.categories['best-practices'].title,
value: report.categories['best-practices'].score,
desiredSize: 'larger',
},
{
name: report.categories.seo.title,
value: report.categories.seo.score,
desiredSize: 'larger',
},
{
name: report.categories.pwa.title,
value: report.categories.pwa.score,
desiredSize: 'larger',
},
];
return {
subject: url,
metrics: metrics,
};
};
/**
* Reducer which will calculate an avarage value of all page measurements
* @param pages {Object} — accumulator
* @param page {Object} — page
* @param page {Object} — page with avarage metrics values
*/
const mergeMetrics = (pages, page) => {
if (!pages) return page;
return {
subject: pages.subject,
metrics: pages.metrics.map((measure, index) => {
let value = (measure.value + page.metrics[index].value)/2;
value = +value.toFixed(2);
return {
...measure,
value,
}
}),
}
}
/**
* Returns urls array splited to chunks accordin to cors number
*
* @param urls {String[]} — URLs array
* @param cors {Number} — count of available cors
* @return {Array<String[]>} — URLs array splited to chunks
*/
function chunkArray(urls, cors) {
const chunks = [...Array(cors)].map(() => []);
let index = 0;
urls.forEach((url) => {
if (index > (chunks.length - 1)) {
index = 0;
}
chunks[index].push(url);
index += 1;
});
return chunks;
}
const urls = [
'/inloggen',
'/wachtwoord-herstellen-otp',
'/lp/service',
'/send-request-to/ww-tammer',
'/post-service-request/binnenschilderwerk',
];
(async () => {
if (cluster.isMaster) {
// Parent proccess
const chunks = chunkArray(urls, numCPUs);
chunks.map(chunk => {
const worker = cluster.fork();
worker.send(chunk);
});
let report = [];
let reportsCount = 0;
cluster.on('message', (worker, msg) => {
report = [...report, ...msg];
worker.disconnect();
reportsCount++;
if (reportsCount === chunks.length) {
fs.writeFileSync(`./performance.json`, JSON.stringify(report));
process.exit(0);
}
});
} else {
// Child process
process.on('message', async (urls) => {
const browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox', '--headless'],
});
const builder = buildReport(browser);
const report = [];
for (let url of urls) {
// Let's measure MEASURES_COUNT times and calculate the avarage
let measures = [];
let index = MEASURES_COUNT;
while(index--){
const metric = await builder(url);
measures.push(metric);
}
const measure = measures.reduce(mergeMetrics);
report.push(measure);
}
cluster.worker.send(report);
await browser.close();
});
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.