INP : la nouvelle métrique qui change tout
Interaction to Next Paint (INP) a remplacé FID en mars 2024. Là où FID ne mesurait que le premier input delay, INP mesure la latence complète de toutes les interactions sur le cycle de vie de la page.
Le seuil 'Bon' est < 200 ms (vs 100 ms pour FID). Ça paraît permissif, mais en pratique c'est plus exigeant : il ne suffit plus d'avoir un premier input rapide, il faut que TOUTES les interactions soient fluides.
Causes principales d'INP élevé : handlers click longs (calculs lourds, appels API bloquants), hydratation JS massive, third-party scripts qui monopolisent le thread principal, animations JS non optimisées.
Réduire INP : 5 techniques efficaces
1. Déportez les calculs lourds hors du thread principal : Web Workers pour les transformations complexes, `requestIdleCallback` pour les tâches différables.
2. Évitez les `setTimeout(0)` et autres 'yield hacks'. Préférez `scheduler.yield()` (Chrome 129+) qui rend la main proprement au navigateur.
3. Coupez le JavaScript en chunks (code splitting par route, dynamic imports pour les composants lourds non-critiques). Sur Next.js, utilisez `dynamic(() => import('...'), { ssr: false })` pour les îlots non-essentiels.
4. Tierces : defer ou async systématique, `requestIdleCallback` pour les scripts analytics non-critiques, voire Partytown pour déporter dans un Web Worker.
5. Réduisez l'hydration : React Server Components (Next.js 15) hydrate moins de DOM, ce qui libère le thread principal pour les interactions.
LCP : passage sous les 2 secondes
LCP (Largest Contentful Paint) reste à 2,5 s pour le seuil 'Bon', mais Google a indiqué une direction vers 2 s pour 2025-2026. Visez 2 s dès maintenant.
Sur Next.js, l'optimisation LCP passe par : préchargement de l'image hero (`priority` sur `next/image`), self-host des polices (next/font), préconnexion aux domaines tiers (`<link rel="preconnect">`), suppression du rendu-bloquant CSS critique.
Sur l'hero de VALRY LABS : image AVIF (et WebP fallback), polices self-hostées (geist), et une aurora background animée qui n'attend pas JS pour démarrer. Résultat : 0,9 s sur mobile 4G.
Le piège classique : les carrousels. Un carousel retarde le LCP car le navigateur ne sait pas quelle slide afficher en premier. Préférez une image statique forte, le carousel peut venir ensuite.
CLS : la stabilité visuelle
CLS < 0,05 est atteignable sur tous les sites avec un peu de rigueur. Le principe : réserver l'espace des éléments dynamiques AVANT qu'ils ne chargent.
Images et vidéos : toujours spécifier `width` et `height` (ou `aspect-ratio` en CSS). `next/image` gère ça automatiquement quand vous fournissez les dimensions.
Bannières cookie, pop-ins, publicités : réservent leur emplacement dès le premier paint, pas de décalage après coup. Les bannières cookie collées en bas (pas de décalage du contenu) sont préférées aux modals.
Fonts : `font-display: swap` évite le FOIT mais peut causer du CLS si la police de secours a des métriques différentes. Utilisez `size-adjust` ou les `font-face` `ascent-override` pour aligner.
Mesure : lab vs field
Lighthouse et PageSpeed Insights mesurent en lab (simulation). Search Console et CrUX mesurent en field (données réelles utilisateurs). Les deux sont importants et ne donnent pas toujours les mêmes résultats.
Règle : optimisez d'abord en lab pour identifier les axes, puis validez en field avec CrUX. Le field data est ce qui compte pour le SEO Google.
En production, installez le `web-vitals` JS library pour remonter les métriques réelles vers votre analytics (Plausible, GA4, ou maison). Suivez les percentiles p75, pas les moyennes.