Tutoriels

Core Web Vitals et Next.js : comment atteindre 100/100 sur Lighthouse

Guide technique pour optimiser les Core Web Vitals avec Next.js : LCP, INP, CLS. Comment next/image, next/font et le rendu statique propulsent Lighthouse à 95-100.

Spectre Digital20 avril 20269 min de lecture
Core Web Vitals et Next.js : comment atteindre 100/100 sur Lighthouse

En résumé

Next.js atteint nativement des scores Lighthouse entre 95 et 100 grâce à trois mécanismes : next/image (WebP automatique + lazy loading + dimensionnement responsive), next/font (préchargement zéro layout shift), et la génération statique (pages pré-rendues servies depuis un CDN). Les Core Web Vitals sont facteur de classement Google depuis mai 2021 — un LCP supérieur à 2,5s fait perdre des positions dans les SERP.

Les Core Web Vitals sont un signal de classement Google depuis mai 2021 (Google Search Central). En 2026, un site lent ne perd pas seulement des visiteurs — il perd des positions dans les SERP, mécaniquement.

Next.js adresse ces métriques nativement, sans plugin tiers ni configuration avancée. Ce guide explique comment next/image, next/font et la génération statique propulsent Lighthouse entre 95 et 100.


Que sont les Core Web Vitals en 2026 ?

Les Core Web Vitals sont trois métriques définies par Google pour mesurer l'expérience utilisateur réelle. Chaque métrique a des seuils officiels publiés sur web.dev.

LCP — Largest Contentful Paint

Le LCP mesure le temps de rendu du plus grand élément visible à l'écran (image hero, bloc de texte principal). C'est le proxy de Google pour la vitesse de chargement perçue.

SeuilValeur
Good< 2,5 s
Needs Improvement2,5 s – 4 s
Poor> 4 s

INP — Interaction to Next Paint

L'INP remplace le FID (First Input Delay) depuis mars 2024. L'INP mesure la latence de toutes les interactions utilisateur (clics, touches clavier), pas seulement la première.

SeuilValeur
Good< 200 ms
Needs Improvement200 ms – 500 ms
Poor> 500 ms

CLS — Cumulative Layout Shift

Le CLS mesure la stabilité visuelle de la page. Un score élevé signifie que des éléments bougent pendant le chargement — expérience frustrante et pénalisée par Google.

SeuilValeur
Good< 0,1
Needs Improvement0,1 – 0,25
Poor> 0,25

Comment Next.js optimise le LCP automatiquement

Le LCP est presque toujours causé par une image hero ou un bloc de texte chargé trop tard. next/image résout ce problème à plusieurs niveaux simultanément.

Conversion automatique en WebP/AVIF. Next.js convertit toutes les images à la volée au format WebP (réduction moyenne de 30 % vs JPEG) ou AVIF (réduction de 50 % vs JPEG). Aucune conversion manuelle nécessaire.

Lazy loading par défaut. Toutes les images avec next/image se chargent uniquement quand elles entrent dans le viewport. Les images hors écran ne retardent pas le LCP.

La prop priority pour les images critiques. L'image hero doit être chargée immédiatement — pas en lazy loading. La prop priority déclenche un <link rel="preload"> automatique.

import Image from "next/image"

// Image hero : priority obligatoire pour le LCP
<Image
  src="/images/hero.jpg"
  alt="Description précise de l'image"
  width=\{1200\}
  height=\{600\}
  priority
  sizes="(max-width: 768px) 100vw, 1200px"
/>

La prop sizes pour le dimensionnement responsive. Sans sizes, Next.js génère une image trop grande pour mobile. Avec sizes, le navigateur télécharge exactement la résolution nécessaire selon la taille d'écran.

Selon HTTP Archive (2025), la médiane du LCP mobile sur WordPress est de 4,2 s. Sur les sites Next.js avec next/image correctement configuré, la médiane descend à 1,8 s.


Comment Next.js élimine le CLS

Le CLS est souvent causé par deux éléments : les fonts qui se substituent (FOUT/FOIT) et les images sans dimensions déclarées.

next/font : zéro layout shift sur les polices.

next/font précharge les polices Google et les auto-héberge sur votre CDN. Le navigateur n'a jamais besoin de télécharger la police depuis les serveurs Google — elle est disponible immédiatement.

import { DM_Sans } from "next/font/google"

const dmSans = DM_Sans(\{
  subsets: ["latin"],
  display: "swap",   // Fallback visible pendant le chargement
  variable: "--font-dm-sans",
\})

Sans next/font, le navigateur affiche d'abord une police système, puis substitue la police Google quand elle arrive — provoquant un décalage visible (CLS). Avec next/font, la police est disponible dès le premier rendu.

Dimensions obligatoires sur next/image.

next/image exige de déclarer width et height (ou d'utiliser fill). Cette obligation force le navigateur à réserver l'espace exact de l'image avant qu'elle soit chargée — CLS zéro garanti.

// Correct : dimensions déclarées, espace réservé
<Image src="/photo.jpg" alt="..." width=\{800\} height=\{450\} />

// Correct avec fill : parent en position relative avec hauteur définie
<div style=\{\{ position: "relative", height: "450px" \}\}>
  <Image src="/photo.jpg" alt="..." fill />
</div>

Génération statique vs rendu côté serveur : impact sur les Core Web Vitals

Le mode de rendu est le facteur le plus impactant sur le TTFB (Time to First Byte), qui influence directement le LCP.

SSG — Static Site Generation (recommandé)

Les pages sont pré-rendues au moment du build et servies depuis le CDN. Le TTFB est de 20 à 60 ms — la page est déjà construite, il suffit de la livrer.

  • LCP : optimal (contenu disponible immédiatement)
  • INP : optimal (pas de calcul serveur côté client)
  • CLS : optimal si next/image et next/font sont utilisés

SSR — Server-Side Rendering

Les pages sont rendues à la demande pour chaque requête. Le TTFB monte à 200–800 ms selon la complexité des calculs serveur.

  • LCP : dégradé (attente du rendu serveur avant envoi au navigateur)
  • À utiliser uniquement pour les pages avec données personnalisées par utilisateur

CSR — Client-Side Rendering

Le HTML initial est vide, le contenu est injecté par JavaScript après chargement. Google peut indexer le CSR, mais le LCP est systématiquement dégradé.

  • LCP : très dégradé (le plus grand élément n'est visible qu'après exécution JS)
  • À éviter pour les pages indexées par Google

Pour Onyx et les sites vitrines/blogs, SSG est le choix par défaut. La documentation complète d'Onyx couvre la configuration du rendu statique.


Comment mesurer ses Core Web Vitals avec Next.js

Mesurer avant d'optimiser. Quatre outils couvrent l'ensemble des besoins.

Lighthouse (Chrome DevTools)

Outil intégré dans Chrome — accès via F12 > Onglet Lighthouse. Mesure en environnement simulé (mobile 4G throttled). Utile pour le développement local. Limitation : les résultats varient selon la machine et les extensions Chrome actives.

PageSpeed Insights (Google)

pagespeed.web.dev — mesure les données de terrain réelles (CrUX) combinées aux données de lab. C'est la source de vérité pour Google. Les données de terrain reflètent l'expérience réelle des derniers 28 jours de vos visiteurs.

Google Search Console

Le rapport "Expérience de page" dans Search Console agrège les Core Web Vitals réels de tout votre site, page par page. C'est ici que vous voyez l'impact SEO réel de vos métriques.

La librairie web-vitals

Pour mesurer en production avec vos propres données analytiques :

import { onLCP, onINP, onCLS } from "web-vitals"

onLCP(console.log)
onINP(console.log)
onCLS(console.log)

Intégrable avec Google Analytics 4, Plausible, ou tout outil d'analytics custom.


Les erreurs courantes qui dégradent le score Lighthouse

Ces erreurs sont fréquentes et chacune a un fix simple.

Images sans dimensions explicites → CLS élevé

Symptôme : CLS > 0,1, éléments qui bougent pendant le chargement. Fix : toujours déclarer width et height sur next/image, ou utiliser fill avec un parent dimensionné.

Fonts sans display: swap → FCP dégradé

Symptôme : texte invisible pendant 2–3 s (FOIT — Flash of Invisible Text). Fix : ajouter display: "swap" dans la configuration next/font. Onyx l'applique par défaut dans src/lib/fonts.ts.

JavaScript non utilisé → LCP dégradé

Symptôme : score "Reduce unused JavaScript" dans Lighthouse. Le parseur JS bloque le rendu. Fix : utiliser dynamic() de Next.js pour les composants lourds non critiques au premier rendu.

import dynamic from "next/dynamic"

// Chargé uniquement si l'utilisateur interagit
const HeavyChart = dynamic(() => import("./HeavyChart"), \{ ssr: false \})

Images non optimisées (PNG/JPEG bruts) → LCP dégradé

Symptôme : images > 200 KB dans le rapport Lighthouse. Fix : utiliser exclusivement next/image — la conversion WebP/AVIF est automatique.

Trop de ressources bloquantes (CSS tiers) → FCP dégradé

Symptôme : score "Eliminate render-blocking resources". Fix : charger les CSS non critiques en asynchrone, ou les inliner dans <head>.

Requêtes API en cascade côté client → INP dégradé

Symptôme : INP > 200 ms sur les pages avec chargement de données. Fix : préférer le fetching côté serveur (Server Components Next.js 15) plutôt que useEffect + fetch côté client.


Score Lighthouse 95–100 : checklist complète

Cette liste couvre les actions qui ont le plus d'impact. À valider avant chaque déploiement.

Images

  • Toutes les images utilisent next/image
  • La prop priority est appliquée sur l'image hero (au-dessus de la ligne de flottaison)
  • width et height déclarés sur toutes les images, ou fill avec parent dimensionné
  • La prop sizes est définie selon les breakpoints réels du layout
  • Aucune image de fond critique en CSS pur (préférer next/image + fill)

Polices

  • Toutes les polices chargées via next/font/google — zéro requête vers fonts.googleapis.com
  • display: "swap" configuré sur chaque police
  • Pas de @font-face manuel dans les CSS

JavaScript

  • Composants lourds chargés avec dynamic() si non critiques au premier rendu
  • "use client" uniquement sur les composants qui utilisent vraiment des hooks ou des event handlers
  • Pas de librairies tierres inutiles dans le bundle (auditer avec next build --debug)

Rendu

  • Pages statiques en SSG par défaut (pas de SSR inutile)
  • Composants React Server par défaut — "use client" uniquement si nécessaire
  • Pas de useEffect pour charger des données indexables par Google

Réseau

  • Compression Gzip/Brotli activée (automatique sur Vercel)
  • Cache-Control configuré pour les assets statiques (automatique sur Vercel)
  • Pas de redirections en chaîne (vérifier dans la Search Console)

Métriques cibles à valider sur PageSpeed Insights (mobile) :

MétriqueCible
LCP< 2,5 s
INP< 200 ms
CLS< 0,1
FCP< 1,8 s
TTFB< 600 ms
Score Lighthouse mobile≥ 95

Conclusion

Les Core Web Vitals ne sont pas une contrainte technique abstraite — ce sont des métriques directement liées au classement Google et à l'expérience utilisateur réelle. Un LCP de 4 s fait perdre des positions et des visiteurs simultanément.

Next.js avec next/image, next/font et la génération statique atteint ces scores nativement. Le template Onyx, optimisé Core Web Vitals par défaut, fournit une base Lighthouse 95+ prête à déployer sans configuration supplémentaire.

Pour approfondir le SEO technique au-delà des Core Web Vitals, consultez notre guide SEO avec Onyx — métadonnées, JSON-LD, sitemap et données structurées.

Une analyse complète des stratégies de performance web en 2026 est disponible dans notre article performances site web 2026.

Partager :