Moniteur Web Vitals dans l'onglet — LCP / CLS / INP dans l'Output Console sans DevTools
Les Web Vitals (LCP, CLS, INP) sont 3 métriques que Google utilise comme facteur de classement SEO. La façon standard de les mesurer : Lighthouse dans les DevTools — 30 secondes par audit, déclenchement manuel. Alternative : l'API PerformanceObserver intégrée aux navigateurs. Plus une règle JS JustZix = un moniteur passif qui rapporte dans l'Output Console pour chaque page visitée. Parfait pour un contrôle rapide de vos propres projets ou l'analyse des concurrents.
Règle JS — capture complète des Web Vitals
Scope : *://*/* ou par domaine si vous voulez seulement surveiller vos propres sites.
// Règle JS « Moniteur Web Vitals »
const vitals = { LCP: null, CLS: 0, FCP: null, TTFB: null, INP: null };
// === LCP (Largest Contentful Paint) ===
new PerformanceObserver((list) => {
const entries = list.getEntries();
const last = entries[entries.length - 1];
vitals.LCP = Math.round(last.startTime);
}).observe({ type: 'largest-contentful-paint', buffered: true });
// === CLS (Cumulative Layout Shift) ===
let clsEntries = [];
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
clsEntries.push(entry);
vitals.CLS = clsEntries.reduce((s, e) => s + e.value, 0);
}
}
}).observe({ type: 'layout-shift', buffered: true });
// === FCP (First Contentful Paint) ===
new PerformanceObserver((list) => {
const fcp = list.getEntries().find(e => e.name === 'first-contentful-paint');
if (fcp) vitals.FCP = Math.round(fcp.startTime);
}).observe({ type: 'paint', buffered: true });
// === TTFB (Time to First Byte) ===
const nav = performance.getEntriesByType('navigation')[0];
if (nav) vitals.TTFB = Math.round(nav.responseStart - nav.requestStart);
// === INP (Interaction to Next Paint) ===
let worstINP = 0;
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > worstINP) {
worstINP = Math.round(entry.duration);
vitals.INP = worstINP;
}
}
}).observe({ type: 'event', buffered: true, durationThreshold: 16 });
// Rapport 5 secondes après le chargement + au unload (valeurs finales)
const report = () => {
const status = (val, good, poor) =>
val === null ? '?' : val <= good ? '✓' : val <= poor ? '⚠' : '✗';
JUSTZIX.log('=== Web Vitals ===');
JUSTZIX.log(`LCP: ${vitals.LCP ?? '?'}ms ${status(vitals.LCP, 2500, 4000)} (cible <2.5s)`);
JUSTZIX.log(`CLS: ${vitals.CLS.toFixed(3)} ${status(vitals.CLS, 0.1, 0.25)} (cible <0.1)`);
JUSTZIX.log(`FCP: ${vitals.FCP ?? '?'}ms ${status(vitals.FCP, 1800, 3000)} (cible <1.8s)`);
JUSTZIX.log(`TTFB: ${vitals.TTFB ?? '?'}ms ${status(vitals.TTFB, 800, 1800)} (cible <800ms)`);
JUSTZIX.log(`INP: ${vitals.INP ?? '?'}ms ${status(vitals.INP, 200, 500)} (cible <200ms)`);
};
setTimeout(report, 5000);
window.addEventListener('beforeunload', report);
JUSTZIX.info(`[Vitals] Moniteur actif pour ${location.hostname}`);
Ce que vous voyez dans l'Output Console
5 secondes après le chargement :
[INFO] [Vitals] Moniteur actif pour www.justzix.com
[LOG] === Web Vitals ===
[LOG] LCP: 1240ms ✓ (cible <2.5s)
[LOG] CLS: 0.024 ✓ (cible <0.1)
[LOG] FCP: 680ms ✓ (cible <1.8s)
[LOG] TTFB: 145ms ✓ (cible <800ms)
[LOG] INP: 85ms ✓ (cible <200ms)
Chaque métrique avec un statut visuel :
- ✓ = dans la bonne plage (le « Good » de Google)
- ⚠ = dans la plage « Needs improvement »
- ✗ = dans la plage « Poor »
Cas d'usage 1 — auditer votre propre site sans Lighthouse
Classique : déployer sur staging, ouvrir l'onglet, vérifier si les Web Vitals sont au vert. Avec Lighthouse : 30 s d'attente. Avec JustZix : 5 s, et il rapporte pour chaque page suivante visitée dans cette session.
Cas d'usage 2 — comparer aux concurrents
Visitez un concurrent. L'Output Console affiche ses LCP/CLS/INP. Votre site — comparaison 1:1, mêmes conditions réseau, même appareil.
Cas d'usage 3 — moniteur en direct pendant le développement
Snappez un pane Output Console sur le côté droit. Lancez votre serveur dev localhost. Chaque F5 → un JUSTZIX.log avec des vitals fraîches. Vous voyez en direct l'effet de vos changements (p. ex. image lazy-load → LCP en hausse, layout shift → CLS en hausse).
Cas d'usage 4 — export JSON avec une action BOUTON
// Action BOUTON « 📊 Exporter les vitals »
const data = {
url: location.href,
timestamp: new Date().toISOString(),
vitals: window.JZ_LATEST_VITALS || {}
};
const json = JSON.stringify(data, null, 2);
navigator.clipboard.writeText(json);
JUSTZIX.log('Vitals exportées vers le presse-papiers.');
Dans la règle JS, ajoutez une ligne : window.JZ_LATEST_VITALS = vitals; après chaque mise à jour. Le BOUTON a maintenant le snapshot courant à exporter vers la doc / Slack.
Pièges
- LCP dans les single-page apps. Les changements de route SPA ne déclenchent pas de nouvelle mesure LCP. Contournement : écoutez les événements popstate et réinitialisez les observers.
- Le CLS continue après le chargement. Les pages avec images lazy-load peuvent augmenter le CLS pendant des heures. CLS final = valeur au unload (beforeunload). Lighthouse arrête de mesurer après 3-5 s.
- L'INP exige une interaction réelle. Une page statique sans clics → INP = null. Ouvrez la page + scrollez/cliquez avant de lire les métriques.
- TTFB = responseStart - requestStart, SANS DNS/connexion. Le TTFB complet est
responseStart - fetchStart. Les implémentations varient. - PerformanceObserver buffered: true — capture les événements survenus avant l'initialisation de l'observer. Sans ça, les entrées pré-init sont perdues.
La suite
- Output Console en détail — où atterrit JUSTZIX.log
- Déboguer GTM sans devs — pattern de monitoring jumeau
- window.JZ + JUSTZIX — API programmatique
Installez JustZix — un moniteur Web Vitals zéro-config qui REMARQUE le problème avant l'utilisateur.
Notez cet article
Aucune note — soyez le premier.