Skip to content

Instantly share code, notes, and snippets.

@tunetheweb
Last active June 2, 2023 12:17
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tunetheweb/20ffc5719352dd86c215636729760c5c to your computer and use it in GitHub Desktop.
Save tunetheweb/20ffc5719352dd86c215636729760c5c to your computer and use it in GitHub Desktop.
// Credit to Michal Mocny (https://twitter.com/mmocny)
//
// Copy and paste this into the console and click around to see all interactions, whether they would pass INP,
// and if you expand the entry you'll see the debug breakdown information.
//
// This is basically the same as the Core Web Vitals extension does: https://web.dev/debug-cwvs-with-web-vitals-extension/
const valueToRating = (score) => score <= 200 ? 'good' : score <= 500 ? 'needs-improvement' : 'poor';
const COLOR_GOOD = '#0CCE6A';
const COLOR_NEEDS_IMPROVEMENT = '#FFA400';
const COLOR_POOR = '#FF4E42';
const RATING_COLORS = {
'good': COLOR_GOOD,
'needs-improvement': COLOR_NEEDS_IMPROVEMENT,
'poor': COLOR_POOR
};
const observer = new PerformanceObserver((list) => {
const interactions = {};
for (const entry of list.getEntries().filter((entry) => entry.interactionId)) {
interactions[entry.interactionId] = interactions[entry.interactionId] || [];
interactions[entry.interactionId].push(entry);
}
// Will report as a single interaction even if parts are in separate frames.
// Consider splitting by animation frame.
for (const interaction of Object.values(interactions)) {
const entry = interaction.reduce((prev, curr) => prev.duration >= curr.duration ? prev : curr);
const value = entry.duration;
const rating = valueToRating(value);
const formattedValue = `${value.toFixed(0)} ms`;
console.groupCollapsed(
`INP Snippet %c${formattedValue} (${rating})`,
`color: ${RATING_COLORS[rating] || 'inherit'}`
);
console.log('Interaction target:', entry.target);
for (let entry of interaction) {
console.log(`Interaction event type: %c${entry.name}`, 'font-family: monospace');
// RenderTime is an estimate, because duration is rounded, and may get rounded down.
// In rare cases it can be less than processingEnd and that breaks performance.measure().
// Lets make sure its at least 4ms in those cases so you can just barely see it.
const adjustedPresentationTime = Math.max(entry.processingEnd + 4, entry.startTime + entry.duration);
console.table([{
subPartString: 'Input delay',
'Time (ms)': Math.round(entry.processingStart - entry.startTime, 0),
},
{
subPartString: 'Processing time',
'Time (ms)': Math.round(entry.processingEnd - entry.processingStart, 0),
},
{
subPartString: 'Presentation delay',
'Time (ms)': Math.round(adjustedPresentationTime - entry.processingEnd, 0),
}]);
}
console.groupEnd();
}
});
observer.observe({
type: 'event',
durationThreshold: 0, // 16 minimum by spec
buffered: true
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment