studiocms
Version:
Astro Native CMS for AstroDB. Built from the ground up by the Astro community.
63 lines (62 loc) • 2.04 kB
JavaScript
function processWebVitalsRouteSummary(data) {
const grouped = data.reduce(
(acc, item) => {
const key = `${item.route}-${item.name}`;
if (!acc[key]) acc[key] = [];
acc[key].push(item);
return acc;
},
{}
);
const results = [];
for (const metrics of Object.values(grouped)) {
if (metrics.length < 4) continue;
metrics.sort((a, b) => a.rating.localeCompare(b.rating) || a.value - b.value);
const quartileSize = Math.ceil(metrics.length / 4);
metrics.forEach((metric, index) => {
metric.quartile = Math.floor(index / quartileSize) + 1;
});
metrics.forEach((metric, index, arr) => {
const nextItem = arr[index + 1];
metric.quartile_end = !nextItem || nextItem.quartile !== metric.quartile;
});
results.push(...metrics.filter((metric) => metric.quartile === 3 && metric.quartile_end));
}
const summaries = {};
for (const item of results) {
const { route, name, rating, value } = item;
const routeSummary = summaries[route] ||= {
route,
passingCoreWebVitals: true,
metrics: {},
score: 0
};
routeSummary.metrics[name] = {
rating,
value,
sampleSize: results.length
};
if (["LCP", "CLS", "INP"].includes(name) && rating !== "good") {
routeSummary.passingCoreWebVitals = false;
}
}
return Object.values(summaries).filter(
(route) => Boolean(route.metrics.CLS && route.metrics.LCP && route.metrics.INP)
).map((route) => ({
...route,
score: simpleScore(
route.metrics.LCP.rating,
route.metrics.CLS.rating,
route.metrics.INP.rating
)
})).sort((a, b) => a.score - b.score);
}
const weighting = { LCP: 0.4, CLS: 0.3, INP: 0.3 };
const scoring = { good: 1, "needs-improvement": 0.5, poor: 0 };
const simpleScore = (lcpRating, clsRating, inpRating) => scoring[lcpRating] * weighting.LCP + scoring[clsRating] * weighting.CLS + scoring[inpRating] * weighting.INP;
export {
processWebVitalsRouteSummary,
scoring,
simpleScore,
weighting
};