Introduction
Une seconde de délai de chargement réduit vos conversions de 7 %. En 2026, Google utilise les Core Web Vitals comme signal de classement direct — un site lent ou instable est pénalisé dans les résultats de recherche, point. Ces trois métriques (LCP, CLS, INP) mesurent ce que vos utilisateurs ressentent réellement : la vitesse de chargement perçue, la stabilité visuelle et la réactivité aux interactions.
Ce guide couvre chaque métrique en profondeur avec des solutions concrètes, du code d'optimisation pour Nuxt.js, les outils de mesure à utiliser et une checklist prête pour l'audit. Que vous gériez un SaaS, un site vitrine ou une marketplace, ces optimisations ont un impact mesurable sur votre trafic et vos conversions.

Comprendre les Core Web Vitals et Leur Impact SEO
Les Core Web Vitals (CWV) sont un ensemble de métriques créées par Google pour quantifier l'expérience utilisateur réelle sur le web. Depuis 2024, les trois métriques sont :
| Métrique | Mesure | Seuil "Bon" | Seuil "À améliorer" | Seuil "Mauvais" |
|---|---|---|---|---|
| LCP | Vitesse de chargement du plus grand élément visible | < 2,5s | 2,5s – 4s | > 4s |
| CLS | Stabilité visuelle (décalages de layout) | < 0,1 | 0,1 – 0,25 | > 0,25 |
| INP | Réactivité aux interactions utilisateur | < 200ms | 200ms – 500ms | > 500ms |
En 2024, Google a remplacé le FID (First Input Delay) par l'INP (Interaction to Next Paint), une mesure bien plus exigeante : là où le FID ne mesurait que la première interaction, l'INP mesure la réactivité de toutes les interactions tout au long de la visite.
Pourquoi les CWV Impactent Directement Votre Business
Les données sont sans appel :
- Taux de rebond — chaque 100ms de latence supplémentaire augmente le bounce rate de 1,4 %
- Conversions — les sites avec un LCP < 2,5s convertissent 21 % mieux que ceux au-dessus de 4s
- SEO — à contenu égal, Google favorise les pages avec de meilleurs CWV dans les résultats
Optimiser vos Core Web Vitals n'est pas un exercice technique isolé — c'est un investissement direct dans votre chiffre d'affaires. C'est aussi un marqueur du développement web haut de gamme.
LCP (Largest Contentful Paint) : Accélérer le Chargement Perçu
Le LCP mesure le temps qu'il faut pour que le plus grand élément visible de la page se charge — typiquement une image hero, un bloc de texte principal ou une vidéo. L'objectif : moins de 2,5 secondes.
Causes Courantes d'un LCP Élevé
- Images lourdes ou non optimisées — formats anciens (JPEG/PNG non compressés), dimensions excessives
- Ressources bloquant le rendu — CSS et JS synchrones non critiques retardent le premier affichage
- Temps de réponse serveur lent (TTFB) — hébergement mutualisé, base de données non optimisée, absence de cache Redis
- Absence de CDN — les utilisateurs distants subissent une latence réseau élevée
- Rendu côté client excessif — les SPAs qui rendent le contenu principal via JavaScript après le chargement
Solutions LCP : Code et Techniques
1. Preload de l'image LCP avec priorité haute
Ne lazy-loadez jamais l'image LCP — c'est l'inverse de ce que vous voulez. Préchargez-la :
<!-- Dans le <head> -->
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high" />
<!-- Dans le body — PAS de lazy loading sur l'image LCP -->
<img src="/hero.webp" alt="..." width="1200" height="630" fetchpriority="high" />
2. Formats d'image modernes avec fallback
<picture>
<source srcset="/hero.avif" type="image/avif" />
<source srcset="/hero.webp" type="image/webp" />
<img src="/hero.jpg" alt="..." width="1200" height="630" fetchpriority="high" />
</picture>
AVIF offre une compression 30-50 % meilleure que WebP, lui-même 25-35 % meilleur que JPEG. Le gain de poids se traduit directement en LCP plus rapide.
3. CSS critique inline + chargement asynchrone du reste
<head>
<!-- CSS critique directement dans le HTML -->
<style>
/* Seulement les styles above-the-fold */
.hero { ... }
.nav { ... }
</style>
<!-- CSS non critique chargé en asynchrone -->
<link rel="preload" href="/styles.css" as="style"
onload="this.rel='stylesheet'" />
<noscript><link rel="stylesheet" href="/styles.css" /></noscript>
</head>
4. Optimisation du TTFB
| Action | Impact TTFB | Complexité |
|---|---|---|
| Activer le cache navigateur (Cache-Control) | -30 à -50 % | Faible |
| CDN (Cloudflare, Vercel Edge) | -40 à -70 % | Faible |
| Cache serveur (Redis, Varnish) | -50 à -80 % | Moyenne |
| SSR / ISR au lieu de CSR | -60 à -90 % | Moyenne |
| HTTP/3 + Brotli | -10 à -20 % | Faible |
Pour choisir la bonne infrastructure, consultez notre comparatif Serverless, conteneurs ou VPS.
CLS (Cumulative Layout Shift) : Éliminer les Décalages Visuels
Le CLS mesure la stabilité visuelle — ces moments frustrants où un bouton se déplace juste quand vous allez cliquer dessus, ou un paragraphe saute vers le bas à cause d'une image qui se charge. L'objectif : score inférieur à 0,1.
Causes Courantes d'un CLS Élevé
- Images et vidéos sans dimensions — le navigateur ne sait pas quelle place réserver
- Polices web qui chargent tard — le texte en police de fallback est remplacé par la police web, causant un re-layout (FOUT — Flash of Unstyled Text)
- Contenu injecté dynamiquement — bannières cookie, publicités, notifications qui poussent le contenu
- Iframes sans dimensions — embeds YouTube, widgets tiers
Solutions CLS : Code et Techniques
1. Toujours spécifier les dimensions des médias
<!-- ❌ Cause du CLS -->
<img src="/photo.webp" alt="..." />
<!-- ✅ Pas de CLS -->
<img src="/photo.webp" alt="..." width="800" height="450" />
<!-- ✅ Responsive avec aspect-ratio CSS -->
<img src="/photo.webp" alt="..."
style="aspect-ratio: 16/9; width: 100%; height: auto;" />
2. Optimisation du chargement des polices
/* Précharger la police principale */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-var.woff2') format('woff2');
font-display: swap; /* Affiche le texte immédiatement en fallback */
font-weight: 100 900;
unicode-range: U+0000-00FF; /* Sous-ensemble latin uniquement */
}
<!-- Preload dans le <head> -->
<link rel="preload" href="/fonts/inter-var.woff2" as="font"
type="font/woff2" crossorigin />
font-display: swap est le meilleur compromis : le texte s'affiche immédiatement avec la police de fallback, puis bascule en douceur quand la police web est prête. font-display: optional est encore mieux pour le CLS (pas de swap du tout) mais risque de ne pas afficher votre police sur les connexions lentes.
3. Bannière cookie sans CLS
/* ❌ Bannière qui pousse le contenu vers le bas */
.cookie-banner {
position: relative;
}
/* ✅ Bannière qui se superpose au contenu */
.cookie-banner {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 50;
}
4. Réserver l'espace pour le contenu dynamique
/* Réserver la taille d'un emplacement publicitaire */
.ad-slot {
min-height: 250px;
width: 300px;
background: var(--color-surface-muted);
}
/* Skeleton loader au lieu d'un espace vide */
.skeleton {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
INP (Interaction to Next Paint) : Rendre Votre Site Réactif
L'INP mesure la latence entre une interaction utilisateur (clic, tap, frappe clavier) et la mise à jour visuelle correspondante. Contrairement au FID qui ne mesurait que la première interaction, l'INP capture la pire interaction sur toute la visite. L'objectif : moins de 200ms.
Causes Courantes d'un INP Élevé
- JavaScript lourd sur le main thread — calculs complexes, parsing JSON volumineux, manipulation DOM massive
- Event handlers lents — opérations synchrones dans les gestionnaires de clic
- Third-party scripts — analytics, chat widgets, A/B testing qui bloquent le thread principal
- Hydratation coûteuse — les frameworks SSR (Nuxt, Next) exécutent beaucoup de JS au chargement
Solutions INP : Code et Techniques
1. Céder le main thread (yield)
La technique la plus sous-utilisée mais la plus puissante pour l'INP — permettre au navigateur de traiter les mises à jour visuelles entre les tâches lourdes :
// Fonction utilitaire pour yield
function yieldToMain() {
return new Promise(resolve => setTimeout(resolve, 0));
}
// ❌ Bloque le main thread pendant toute la boucle
function processItems(items: Item[]) {
items.forEach(item => heavyComputation(item));
}
// ✅ Yield après chaque batch de 50 items
async function processItems(items: Item[]) {
for (let i = 0; i < items.length; i += 50) {
const batch = items.slice(i, i + 50);
batch.forEach(item => heavyComputation(item));
await yieldToMain();
}
}
2. Débouncer et throttler les interactions fréquentes
// Throttle pour les événements de scroll/resize
function throttle<T extends (...args: any[]) => void>(fn: T, ms: number): T {
let lastCall = 0;
return ((...args: any[]) => {
const now = Date.now();
if (now - lastCall >= ms) {
lastCall = now;
fn(...args);
}
}) as T;
}
// Debounce pour les champs de recherche
function debounce<T extends (...args: any[]) => void>(fn: T, ms: number): T {
let timer: ReturnType<typeof setTimeout>;
return ((...args: any[]) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), ms);
}) as T;
}
// Usage
window.addEventListener('scroll', throttle(handleScroll, 100));
searchInput.addEventListener('input', debounce(handleSearch, 300));
3. Web Workers pour les calculs lourds
// worker.ts
self.onmessage = (e: MessageEvent) => {
const result = heavyComputation(e.data);
self.postMessage(result);
};
// main.ts — le calcul ne bloque plus le main thread
const worker = new Worker('/worker.js');
worker.postMessage(largeDataset);
worker.onmessage = (e) => {
updateUI(e.data);
};
4. Lazy import des modules lourds
// ❌ Import statique — chargé au démarrage, bloque l'INP
import { Chart } from 'chart.js';
// ✅ Import dynamique — chargé au moment de l'interaction
async function showChart(data: ChartData) {
const { Chart } = await import('chart.js');
new Chart(canvas, { data });
}
Optimisations Spécifiques à Nuxt.js
Nuxt.js offre des avantages natifs pour les CWV grâce au SSR, mais quelques configurations supplémentaires font une différence majeure :
// nuxt.config.ts — optimisations CWV
export default defineNuxtConfig({
experimental: {
payloadExtraction: true, // Réduit la taille du payload d'hydratation
renderJsonPayloads: true // JSON plus léger pour l'hydratation
},
nitro: {
compressPublicAssets: true, // Compression Brotli des assets
routeRules: {
'/': { prerender: true },
'/pricing': { swr: 3600 }, // Stale-while-revalidate 1h
'/api/**': { cors: true, headers: { 'Cache-Control': 'max-age=60' } }
}
},
image: {
format: ['avif', 'webp'],
quality: 80,
screens: { xs: 320, sm: 640, md: 768, lg: 1024, xl: 1280 }
},
app: {
head: {
link: [
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
{ rel: 'dns-prefetch', href: 'https://cdn.example.com' }
]
}
}
})
<!-- Composant NuxtImg avec optimisation automatique -->
<template>
<NuxtImg
src="/hero.jpg"
alt="Hero image"
width="1200"
height="630"
format="avif"
quality="80"
sizes="100vw sm:640px md:768px lg:1024px"
:preload="true"
fetchpriority="high"
/>
</template>
Mesurer vos Core Web Vitals : Les Outils Essentiels
| Outil | Type | Données | Utilisation |
|---|---|---|---|
| PageSpeed Insights | Lab + Field | CrUX (réelles) + Lighthouse (labo) | Audit rapide d'une URL |
| Google Search Console | Field | CrUX agrégé par page/groupe | Vue d'ensemble du site |
| Chrome DevTools | Lab | Performance panel, traces | Debugging détaillé |
| web-vitals (JS) | Field | Métriques réelles en production | Monitoring continu |
| Lighthouse CI | Lab | Scores automatisés | CI/CD pipeline |
Tracker les CWV en Production
// plugins/web-vitals.client.ts
import { onLCP, onCLS, onINP } from 'web-vitals';
function sendToAnalytics(metric: { name: string; value: number; id: string }) {
// Envoyer à votre outil d'analytics (PostHog, Datadog, etc.)
posthog.capture('web_vital', {
metric: metric.name,
value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value),
id: metric.id,
page: window.location.pathname
});
}
onLCP(sendToAnalytics);
onCLS(sendToAnalytics);
onINP(sendToAnalytics);
Checklist d'Audit Core Web Vitals
LCP (< 2,5s)
- Image LCP avec
fetchpriority="high"etpreload - Format AVIF/WebP avec fallback
- CSS critique inline, reste asynchrone
- TTFB < 800ms (CDN + cache)
- Pas de lazy loading sur l'élément LCP
CLS (< 0,1)
- Toutes les images/vidéos avec
width+heightouaspect-ratio - Polices avec
font-display: swapet preload - Bannière cookie en
position: fixed - Espaces réservés pour le contenu dynamique
INP (< 200ms)
- Pas de tâche JS > 50ms sur le main thread
- Event handlers avec yield pour les opérations lourdes
- Import dynamique des modules non critiques
- Third-party scripts en
deferouasync
FAQ : Core Web Vitals en 2026
FAQ - Questions fréquentes
Conclusion : La Performance comme Avantage Compétitif
Les Core Web Vitals ne sont pas un caprice technique — ce sont des indicateurs directs de la qualité d'expérience que vous offrez à vos utilisateurs. Un LCP rapide, un CLS stable et un INP réactif se traduisent en meilleur référencement, taux de rebond réduit et conversions en hausse.
Les optimisations présentées dans ce guide sont cumulatives : chaque amélioration individuelle peut sembler modeste, mais l'ensemble transforme l'expérience utilisateur. Commencez par mesurer (PageSpeed Insights), identifiez la métrique la plus dégradée, appliquez les solutions correspondantes, et vérifiez l'impact.
Si vous souhaitez un audit performance complet de votre site ou une optimisation CWV sur votre application Nuxt.js, contactez notre équipe. Nous concevons des applications web sur mesure optimisées pour la performance dès la première ligne de code.




