import { onLCP, onINP, onCLS, Metric } from 'web-vitals';
function sendToAnalytics(metric: Metric) {
// Trimitem doar 10% din trafic (sampling) pentru a economisi resurse
if (Math.random() > 0.1) return;
const body = JSON.stringify({
name: metric.name,
value: metric.value,
rating: metric.rating, // 'good' | 'needs-improvement' | 'poor'
delta: metric.delta,
id: metric.id,
page: window.location.pathname,
});
if (navigator.sendBeacon) {
navigator.sendBeacon('/api/vitals', body);
} else {
fetch('/api/vitals', { body, method: 'POST', keepalive: true });
}
}
export function initWebVitals() {
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
}Salutare. Dacă încă te bazezi doar pe Lighthouse în CI/CD pentru Core Web Vitals, ai mari șanse să ratezi ce se întâmplă real în browserul clienților tăi. Am pățit-o anul trecut pe un SaaS cu ~35k utilizatori lunari, unde pe PageSpeed Insights aveam scor 98, dar în producție INP-ul urlă de durere pe telefoane Mid-Range Android. Hai să vorbim despre cum măsurăm realist LCP, INP și CLS în prod și ce alegem între Vercel Analytics / Speed Insights și o soluție RUM (Real User Monitoring) custom.
De ce te minte Lighthouse și ce înseamnă INP în viața reală
Lighthouse rulează într-un mediu simulat, pe o conexiune throttled artificial, pe un singur device static. Nu dă click-uri pe meniuri drop-down, nu deschide modal-uri grele și nu simulează lag-ul pe care îl provoacă un script terț de cookie banner sau chat widget.
INP (Interaction to Next Paint) a înlocuit definitiv FID-ul și măsoară exact latența la orice interacțiune: click, tap, tastat. La proiectul de care vă ziceam, aveam un component de filtrat produse în React fără useTransition. Pe laptopul meu M1 răspundea în 15ms. La utilizatorii reali cu telefoane ieftine, INP-ul sărea frecvent de 320ms, ceea ce ne strica scorul P75 în Google Search Console și ne trăgea SEO-ul în jos.
Vercel Analytics / Speed Insights: Bune, dar cu costuri ascunse
Vercel îți dă Speed Insights dintr-un click. Funcționează impecabil pe stack-ul lor (Next.js), n-ai ce zice. Îți arată P75 per rută, istoricul pe ultimele 30 de zile și agregarea pe țări sau dispozitive.
Trade-off-ul? Costul și lock-in-ul. Dacă ai trafic serios — să zicem peste 100k evenimente pe lună —, planurile lor pot deveni scumpe rapid. În plus, datele rămân în ecosistemul Vercel. Dacă vrei să corelezi o scădere de INP cu o eroare din Sentry sau cu un spike în CPU pe backend-ul tău Node, trebuie să faci balet între 3 tab-uri diferite.
Varianta Custom RUM: Librăria web-vitals + Endpoint propriu
Cea mai flexibilă alternativă pe care o folosesc acum pe 2 proiecte mari este pachetul oficial web-vitals de la Google, trimis direct într-un endpoint de tip /api/vitals sau într-un beacon backend.
Trimiți datele direct în ClickHouse, Grafana Loki sau un PostHog self-hosted. Ai control 100% pe eșantionare (sampling rate). Nu trebuie să trimiți 100% din sesiuni dacă ai trafic uriaș — 10% e mai mult decât suficient ca să ai un P75 reprezentativ.
Costul e infim (câțiva cenți pe stocare în DB), dar contrapartida e evidentă: trebuie să-ți scrii singur dashboard-urile și să-ți configurezi alertele când INP sare de 200ms.
Vercel e impecabil pentru MVP-uri și proiecte mici-medii unde vrei setup în 2 minute. Când crești și vrei observabilitate unificată cu restul infrastructurii, RUM custom e singura opțiune sustenabilă. Voi cum monitorizați CWV în prod — mergeți pe soluții out-of-the-box gen Vercel/Datadog sau aveți pipeline-ul vostru de date?