Skip to content

Instantly share code, notes, and snippets.

@samzeng
Forked from scurker/perf.js
Created April 25, 2019 09:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samzeng/97f38812780f0a7f94d1dcb0bd804a61 to your computer and use it in GitHub Desktop.
Save samzeng/97f38812780f0a7f94d1dcb0bd804a61 to your computer and use it in GitHub Desktop.
Capturing Page Load Metrics with Puppeteer
const puppeteer = require('puppeteer');
(async function() {
const browser = await puppeteer.launch({ devtools: true });
const page = await browser.newPage();
// Login
await page.goto('http://localhost:8080');
await page.type('#login', 'username');
await page.type('#password', 'password');
await page.$eval('#login', form => form.submit());
await page.waitForNavigation();
// Visit page you want profiled
await page.goto('http://localhost:8080/home');
// Capture page metrics
const metrics = [];
const runs = 10;
const networkSpeed = NETWORK_SPEED.DISABLED;
const useCache = false;
// Simulate Network Speed
await throttleNetwork(networkSpeed);
// Enable/Disable page cache for accurate load times
await page.setCacheEnabled(useCache);
for(let i = 0; i < runs; i++) {
await page.reload({ waitUntil: 'networkidle0' });
metrics.push(await page.evaluate(() => performance.toJSON()));
}
printMetrics(metrics);
console.log('\n');
printAggregateMetrics(metrics);
await browser.close();
async function throttleNetwork(option) {
if(option !== NETWORK_SPEED.DISABLED) {
const client = await page.target().createCDPSession();
console.log(`Using Network Profile [${option.toString()}]\n`);
return client.send('Network.emulateNetworkConditions', NetworkOptions.get(option));
}
}
})();
const NETWORK_SPEED = {
DISABLED: 'off',
SLOW_3G: 'Slow 3G',
FAST_3G: 'Fast 3G',
SLOW_4G: 'Slow 4G',
FAST_4G: 'Fast 4G',
WIFI: 'Wifi'
};
const NetworkOptions = new Map([
[NETWORK_SPEED.SLOW_3G, {
offline: false,
downloadThroughput: 750 * 1024 / 8, // 750 kb/s
uploadThroughput: 250 * 1024 / 8, // 250 kb/s
latency: 40
}],
[NETWORK_SPEED.FAST_3G, {
offline: false,
downloadThroughput: 1.5 * 1024 * 1024 / 8, // 1.5 mb/s
uploadThroughput: 750 * 1024 / 8, // 750 kb/s
latency: 40
}],
[NETWORK_SPEED.SLOW_4G, {
offline: false,
downloadThroughput: 2 * 1024 * 1024 / 8, // 2 mb/s
uploadThroughput: 1.5 * 1024 * 1024 / 8, // 1.5 mb/s
latency: 20
}],
[NETWORK_SPEED.FAST_4G, {
offline: false,
downloadThroughput: 4 * 1024 * 1024 / 8, // 4 mb/s
uploadThroughput: 3 * 1024 * 1024 / 8, // 3 mb/s
latency: 20
}],
[NETWORK_SPEED.Wifi, {
offline: false,
downloadThroughput: 30 * 1024 * 1024 / 8, // 30 mb/s
uploadThroughput: 5 * 1024 * 1024 / 8, // 5 mb/s
latency: 2
}]
]);
function printMetrics(metrics) {
console.log('| Interactive | Loaded | Complete |');
console.log('|-------------|----------|----------|');
metrics.forEach(run => {
const { timing } = run
, { navigationStart, domInteractive, domContentLoadedEventEnd, domComplete } = timing
, toMillis = metric => `${metric - navigationStart}ms`;
console.log(`| ${toMillis(domInteractive).padEnd(11)} | ${toMillis(domContentLoadedEventEnd).padEnd(8)} | ${toMillis(domComplete).padEnd(8)} |`);
});
}
function printAggregateMetrics(metrics) {
console.log('| | Interactive | Loaded | Complete |');
console.log('|-----|-------------|----------|----------|');
const interactive = []
, loaded = []
, complete = []
, avg = arr => (arr.reduce((a, b) => a + b) / arr.length).toFixed(0) + 'ms'
, med = arr => {
let half = Math.floor(arr.length / 2);
return (arr.length % 2 ? arr[half] : (arr[half - 1] + arr[half]) / 2).toFixed(0) + 'ms';
}
, min = arr => arr[0] + 'ms'
, max = arr => arr[arr.length - 1] + 'ms';
metrics.forEach(run => {
let { timing } = run
, { navigationStart } = run.timing
, toMillis = metric => metric - navigationStart;
interactive.push(toMillis(timing.domInteractive, navigationStart));
loaded.push(toMillis(timing.domContentLoadedEventEnd, navigationStart));
complete.push(toMillis(timing.domComplete, navigationStart));
});
interactive.sort();
loaded.sort();
complete.sort();
console.log(`| Avg | ${avg(interactive).padEnd(11)} | ${avg(loaded).padEnd(8)} | ${avg(complete).padEnd(8)} |`);
console.log(`| Med | ${med(interactive).padEnd(11)} | ${med(loaded).padEnd(8)} | ${avg(complete).padEnd(8)} |`);
console.log(`| Min | ${min(interactive).padEnd(11)} | ${min(loaded).padEnd(8)} | ${min(complete).padEnd(8)} |`);
console.log(`| Max | ${max(interactive).padEnd(11)} | ${max(loaded).padEnd(8)} | ${max(complete).padEnd(8)} |`);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment