Skip to content

Instantly share code, notes, and snippets.

@Snugug
Last active March 15, 2019 18:26
Show Gist options
  • Save Snugug/f4cdf1b3836d3f321d4d8bb93d620902 to your computer and use it in GitHub Desktop.
Save Snugug/f4cdf1b3836d3f321d4d8bb93d620902 to your computer and use it in GitHub Desktop.
A Chrome DevTools Snippet to get page performance numbers. Returns interesting Navigation Timings and Resource Sizing. Unfortunate workaround for content types until https://github.com/w3c/resource-timing/issues/203 hits
function getExt(filename, opts) {
if (!opts) opts = {};
if (!filename) return "";
var ext = (/[^./\\]*$/.exec(filename) || [""])[0];
return opts.preserveCase ? ext : ext.toLowerCase();
};
async function typeMap () {
const db = await fetch('https://unpkg.com/mime-db/db.json').then(t => t.json());
const extensions = {};
const types = {};
// source preference (least -> most)
const preference = ['nginx', 'apache', undefined, 'iana'];
Object.keys(db).forEach((type) => {
const mime = db[type];
const exts = mime.extensions;
if (!exts || !exts.length) {
return;
}
// mime -> extensions
extensions[type] = exts;
// extension -> mime
for (let i = 0; i < exts.length; i++) {
const extension = exts[i];
if (types[extension]) {
const from = preference.indexOf(db[types[extension]].source);
const to = preference.indexOf(mime.source);
if (types[extension] !== 'application/octet-stream' &&
(from > to || (from === to && types[extension].substr(0, 12) === 'application/'))) {
// skip the remapping
continue;
}
}
// set the extension -> mime
types[extension] = type;
}
});
return types;
}
(async () => {
const navigation = performance.getEntriesByType('navigation')[0];
const paint = performance.getEntriesByType('paint');
const timings = {
'DOMContentLoaded': navigation.domContentLoadedEventEnd,
'Load': navigation.loadEventEnd - navigation.responseEnd,
'Page Loaded': navigation.duration,
'Response Time': navigation.responseEnd - navigation.requestStart,
};
paint.forEach(entry => timings[entry.name.replace(/\-/g, ' ').replace(/\b\w/g, t => t.toUpperCase())] = entry.startTime);
for (const [key, value] of Object.entries(timings)) {
timings[key] = {'Time (ms)': +(value.toFixed(3)) }
}
console.group('Timing');
console.table(timings);
console.groupEnd('Timing');
console.group('Sizes');
try {
const types = await typeMap();
const resourcesByType = {
'navigation': {
'Number of Items': 1,
'Transfer (KB)': navigation.transferSize,
'Encode (KB)': navigation.encodedBodySize,
'Decode (KB)': navigation.decodedBodySize,
}
};
const resources = performance.getEntriesByType('resource');
const noExtension = {
'Number of Items': 0,
'Transfer (KB)': 0,
'Encode (KB)': 0,
'Decode (KB)': 0,
};
resources.forEach(resource => {
const ext = getExt(resource.name);
const type = types[ext];
if (type) {
if (!resourcesByType[type]) {
resourcesByType[type] = {
'Number of Items': 0,
'Transfer (KB)': 0,
'Encode (KB)': 0,
'Decode (KB)': 0,
};
}
resourcesByType[type]['Number of Items'] += 1;
resourcesByType[type]['Transfer (KB)'] += resource.transferSize;
resourcesByType[type]['Encode (KB)'] += resource.encodedBodySize;
resourcesByType[type]['Decode (KB)'] += resource.decodedBodySize;
} else {
noExtension['Number of Items'] += 1;
noExtension['Transfer (KB)'] += resource.transferSize;
noExtension['Encode (KB)'] += resource.encodedBodySize;
noExtension['Decode (KB)'] += resource.decodedBodySize;
}
});
const totals = {
'Number of Items': 0,
'Transfer (KB)': 0,
'Encode (KB)': 0,
'Decode (KB)': 0,
};
resourcesByType['No Extension'] = noExtension;
for (const [key, value] of Object.entries(resourcesByType)) {
// Add totals together
totals['Number of Items'] += value['Number of Items'];
totals['Transfer (KB)'] += value['Transfer (KB)'];
totals['Encode (KB)'] += value['Encode (KB)'];
totals['Decode (KB)'] += value['Decode (KB)'];
// Convert octets to KB
resourcesByType[key]['Transfer (KB)'] = +((value['Transfer (KB)'] * .001).toFixed(3));
resourcesByType[key]['Encode (KB)'] = +((value['Encode (KB)'] * .001).toFixed(3));
resourcesByType[key]['Decode (KB)'] = +((value['Decode (KB)'] * .001).toFixed(3));
};
for (const[key, value] of Object.entries(totals)) {
if (key !== 'Number of Items') {
totals[key] = +((value * .001).toFixed(3));
}
}
resourcesByType.Total = totals;
console.table(resourcesByType);
} catch(e) {
console.warn('Cannot download application type database');
}
console.groupEnd('Sizes');
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment