Last active
March 15, 2019 18:26
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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