**TL;DR.** Les Core Web Vitals en 2026 sont LCP ≤ 2.5s, INP ≤ 200ms, CLS ≤ 0.1 au p75. Sur les sites de commerce électronique, LCP est fixé via le préchargement de l'image héro, INP via le report de JS et l'utilisation des fonctionnalités concurrentes de React 18+, et CLS via la réservation d'espace pour les images et les régions dynamiques. Google évalue au p75 sur une période de 28 jours ; les corrections mettent des semaines à se refléter.

## Seuils de 2026

| Métrique | Bon    | Besoin d'amélioration | Mauvais  |
| -------- | ------ | --------------------- | -------- |
| LCP      | ≤ 2.5s | 2.5s – 4.0s           | > 4.0s   |
| INP      | ≤ 200ms| 200ms – 500ms         | > 500ms  |
| CLS      | ≤ 0.1  | 0.1 – 0.25            | > 0.25   |
| TTFB     | ≤ 800ms| 800ms – 1.8s          | > 1.8s   |

Source : [web.dev/vitals](https://web.dev/articles/vitals). INP a remplacé FID en tant que Core Web Vital en mars 2024 et reste la métrique pour 2026.

## Pourquoi les CWV sont importants

Google utilise les CWV comme un signal d'expérience de page dans le classement. Les données des utilisateurs réels montrent que les pages avec des CWV entièrement verts surpassent des pages comparables avec de mauvais CWV dans des niches concurrentielles.

Au-delà des classements, les CWV affectent directement la conversion. Des études de 2024 à 2025 montrent de manière cohérente :

- Amélioration de 1 seconde du LCP : augmentation de 5 à 15 % de la conversion sur la PDP.
- INP inférieur à 200ms : réduction de 10 à 20 % de l'abandon de panier.
- CLS inférieur à 0.1 : amélioration notable de la perception de la qualité de l'UX.

## Mesurer de la bonne manière

Deux sources de données sont importantes :

1. **CrUX (Chrome User Experience Report)** : données des utilisateurs réels que Google utilise pour vous classer. Fenêtre mobile de 28 jours, p75. Présenté dans PageSpeed Insights et Search Console.
2. **Votre propre RUM** : données des utilisateurs réels que vous collectez via la bibliothèque `web-vitals` ou votre CDN. Montre des données plus fraîches, vous permet de segmenter par type de page, appareil, pays.

Les outils synthétiques (Lighthouse, WebPageTest) sont utiles pour le diagnostic mais pas pour le scoring.

## Corrections LCP (largest contentful paint)

Sur le commerce électronique, LCP est presque toujours :

- L'image héro sur la page d'accueil, PLP et PDP.
- Le H1 + le premier paragraphe sur les pages de blog/article.

Les grandes victoires :

1. **Préchargez l'image LCP** avec `<link rel="preload" as="image" fetchpriority="high">` :

```html
<link rel="preload" as="image" href="/products/leather-bag/hero.avif" fetchpriority="high" imagesrcset="/products/leather-bag/hero-400.avif 400w, /products/leather-bag/hero-800.avif 800w" imagesizes="(max-width: 768px) 100vw, 50vw" />
```

2. **Utilisez Next.js `<Image>` avec `priority`** sur l'image LCP :

```tsx
<Image
  src={product.heroImage}
  width={800}
  height={800}
  priority
  fetchPriority="high"
  alt={product.altText}
/>
```

3. **Servez des formats modernes**. AVIF bat WebP qui bat JPEG. Next.js Image gère cela automatiquement.

4. **Ne chargez pas l'image LCP en mode lazy**. `loading="lazy"` est uniquement pour les images en dessous de la ligne de flottaison.

5. **Intégrez le CSS critique pour les styles au-dessus de la ligne de flottaison**. Évitez de bloquer le chargement des feuilles de style sur le chemin de rendu critique.

6. **Utilisez le rendu en edge**. TTFB de ≤ 100ms depuis le cache edge vous permet de maximiser le budget LCP.

## Corrections INP (interaction to next paint)

INP mesure le pire cas parmi toutes les interactions sur une page. Un clic lent sur un filtre peut ruiner votre INP pour toute une session.

Les grandes victoires :

1. **Réduisez le JS côté client**. Utilisez les composants serveur React lorsque c'est possible. Chaque kilooctet de JS client nuit à l'INP.

2. **Utilisez `startTransition` pour les mises à jour d'état non urgentes** :

```tsx
import { startTransition, useState } from 'react';

function FilterButton({ filter }) {
  const [isPending, startTransition] = useTransition();
  return (
    <button onClick={() => startTransition(() => applyFilter(filter))}>
      {filter.label}
    </button>
  );
}
```

3. **Utilisez `useOptimistic` pour un retour instantané** :

```tsx
import { useOptimistic } from 'react';

function Cart() {
  const [cart, addOptimistic] = useOptimistic(serverCart);
  return (
    <button onClick={() => {
      addOptimistic({ ...newItem });
      addToCartServerAction(newItem);
    }}>Ajouter au panier</button>
  );
}
```

4. **Débouncer les entrées**. L'autocomplétion de recherche doit être débouncée à 150–250ms avec `AbortController` pour annuler les requêtes en cours :

```tsx
useEffect(() => {
  const controller = new AbortController();
  const timeout = setTimeout(() => {
    fetch(`/api/search?q=${query}`, { signal: controller.signal });
  }, 200);
  return () => {
    clearTimeout(timeout);
    controller.abort();
  };
}, [query]);
```

5. **Évitez de recréer des littéraux regex dans les gestionnaires d'événements** — recréer des regex dans un chemin critique coûte de l'INP mesurable.

6. **Différez les scripts tiers non critiques**. Pixels marketing, widgets de chat, SDK de test A/B : chargez-les avec `strategy="afterInteractive"` ou `lazyOnload`.

## Corrections CLS (cumulative layout shift)

Les grandes victoires :

1. **Définissez toujours la largeur/hauteur sur les images**. Les navigateurs réservent l'espace correct.

```html
<img src="/hero.avif" width="800" height="800" alt="..." />
```

2. **Réservez de l'espace pour le contenu intégré**. Les iframes, publicités, lecteurs vidéo ont besoin de dimensions explicites ou de conteneurs à ratio d'aspect.

3. **Évitez `font-display: swap` sans CSS de fallback de police**. Le swap reflow le texte. Utilisez [size-adjust](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/size-adjust) pour correspondre aux métriques ou acceptez `font-display: optional`.

4. **Ne pas injecter de contenu au-dessus du contenu existant**. Notifications de bannière, consentement aux cookies, bannières de vente — rendez-les dans une position qui ne déplace pas la page.

5. **Les loaders de squelette doivent correspondre aux dimensions du contenu réel**. Un squelette plus petit que le contenu chargé déplace la page.

## Notes spécifiques au type de page

**Page d'accueil**

- L'image héro est LCP. Préchargez-la.
- Les carrousels sont des mines terrestres CLS. Utilisez uniquement CSS ou pré-rendez le premier diaporama.

**PLP (liste de produits / catégorie)**

- LCP est généralement l'image de la première carte produit.
- INP concerne les clics sur les filtres et la pagination. Utilisez `startTransition` de manière agressive.
- CLS est le reflow de la grille de produits lorsque les filtres s'appliquent. Réservez la hauteur de la grille.

**PDP**

- LCP est l'image principale du produit.
- INP concerne le changement de variante et l'ajout au panier. L'UI optimiste est obligatoire.
- CLS est le chargement des vignettes de la galerie de produits après l'image principale.

**Panier / Checkout**

- INP est critique ici. Un bouton "passer commande" lent coûte des commandes.
- CLS provenant du chargement des iframes de paiement (Stripe Elements, etc.). Réservez de l'espace.

## Outils

| Outil                       | À quoi ça sert                                         |
| -------------------------- | ------------------------------------------------------ |
| PageSpeed Insights         | Diagnostic d'URL unique avec superposition des utilisateurs réels (CrUX) |
| Lighthouse                 | Mesure synthétique pour les flux de travail de développement |
| WebPageTest                | Mesure multi-localisation avec limitation de réseau    |
| Search Console → CWV        | Niveau de domaine p75 sur 28 jours                    |
| Votre propre RUM (web-vitals)  | Données de terrain en temps réel segmentées par page, appareil, pays |

## Comment Ordiko gère les CWV par défaut

La pile de la vitrine Ordiko :

- Next.js 16 + React Compiler.
- `cacheComponents: true` + `experimental.ppr: "incremental"`.
- Rendu en edge de coques statiques (TTFB ≤ 100ms).
- Image LCP préchargée par défaut sur PDP, PLP, page d'accueil.
- Limites de suspense autour des îlots dynamiques (panier, récemment consulté, héro personnalisé).
- `startTransition` + `useOptimistic` sur les filtres et les contrôles de variante.
- Recherche débouncée à 200ms avec `AbortController`.

P75 typique des utilisateurs réels sur une PDP Ordiko par défaut : LCP 1.0–1.8s, INP 80–160ms, CLS < 0.05.

## FAQ

**Les Core Web Vitals affectent-ils les classements ?**
Oui, depuis 2021 — mais en tant que critère de départage plutôt qu'un signal principal. Deux pages de qualité de contenu égale seront classées dans l'ordre CWV. Corriger les CWV sur une page mal classée ne la fera pas soudainement remonter si le contenu est faible.

**Pourquoi l'INP est-il plus difficile à corriger que le LCP ?**
Le LCP est principalement un problème de CDN et d'optimisation d'image avec des corrections bien comprises. L'INP est un problème d'exécution JavaScript qui nécessite une analyse composant par composant. Chaque événement d'interaction peut avoir un goulet d'étranglement différent (clic sur filtre vs. ajout au panier vs. changement de variante).

**Quel est un bon objectif INP pour la PDP ?**
Moins de 200ms p75 est 'bon'. Moins de 100ms est réalisable sur des PDP modernes avec discipline (RSC, pas de scripts tiers lourds, entrées débouncées). Au-dessus de 500ms est 'pauvre' et impacte probablement les classements.

**Comment Ordiko gère-t-il les CWV par défaut ?**
Ordiko expédie Next.js 16 Cache Components + PPR, qui diffuse une coque statique avec l'image LCP déjà préchargée et des limites de suspense pour le contenu dynamique. L'INP par défaut est inférieur à 200ms sur des PDP typiques sans optimisation sur mesure.