Next.js et SEO : optimiser les Core Web Vitals et le référencement (2026)
Next.js est excellent pour le SEO grâce au rendu serveur natif. Ce guide vous explique comment optimiser les Core Web Vitals, les métadonnées, les images et les performances pour maximiser votre référencement Google avec Next.js.
Next.js est l’un des meilleurs frameworks pour le SEO : rendu côté serveur, génération statique, gestion native des métadonnées, optimisation d’images intégrée. Voici comment en tirer le maximum pour vos Core Web Vitals et votre positionnement Google.
Pourquoi Next.js est bon pour le SEO
Le problème des SPA React traditionnelles pour le SEO : le HTML initial est vide (juste un div#root), le contenu est chargé par JavaScript. Google peut le crawler mais avec un délai et une fiabilité moindre. Next.js résout ce problème : chaque page est rendue côté serveur (SSR) ou pré-générée (SSG), le HTML livré au navigateur et aux crawlers contient déjà le contenu.
Métadonnées avec l’API Metadata
Dans l’App Router, exportez un objet metadata depuis chaque page :
// app/blog/[slug]/page.tsx
import type { Metadata } from 'next';
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const article = await getArticle(params.slug);
return {
title: article.title,
description: article.excerpt,
openGraph: {
title: article.title,
description: article.excerpt,
type: 'article',
publishedTime: article.publishedAt.toISOString(),
images: [{ url: article.coverImage, width: 1200, height: 630 }],
},
twitter: { card: 'summary_large_image' },
alternates: { canonical: `https://votre-site.fr/blog/${params.slug}` },
};
}
Optimisation des images : next/image
Le composant Image de Next.js optimise automatiquement les images : conversion WebP, responsive srcset, lazy loading natif, réservation d’espace pour éviter le CLS :
import Image from 'next/image';
// Image hero (LCP) : priorité haute, pas de lazy loading
<Image
src="/hero.jpg"
alt="Description"
width={1200}
height={630}
priority // pas de lazy loading pour le LCP
sizes="100vw"
/>
// Images dans une liste : lazy loading automatique
<Image
src={article.cover}
alt={article.title}
width={400}
height={225}
sizes="(max-width: 768px) 100vw, 400px"
/>
Important : définissez toujours width et height (ou utilisez fill avec un conteneur dimensionné). Sans ces attributs, le CLS sera élevé.
LCP : Largest Contentful Paint
Le LCP est l’image ou le texte le plus grand visible dans le viewport initial. Pour l’optimiser dans Next.js :
- Utilisez
prioritysur l’image hero (supprime le lazy loading, ajoute un preload) - Hébergez les polices en self-hosted avec
next/font(élimine le round-trip Google Fonts) - Activez le CDN Vercel ou Cloudflare pour réduire le TTFB
CLS : Cumulative Layout Shift
Le CLS survient quand des éléments bougent pendant le chargement. Causes fréquentes dans Next.js :
- Images sans dimensions définies (toujours définir width/height)
- Polices non préchargées (utilisez
next/font) - Contenu chargé dynamiquement sans réservation d’espace (skeleton loaders)
INP : Interaction to Next Paint
L’INP mesure la réactivité. Dans Next.js, minimisez le JavaScript côté client avec les Server Components. Utilisez "use client" uniquement où c’est nécessaire. Evitez de charger des bibliothèques lourdes côté client — cherchez d’abord une solution serveur.
Données structurées Schema.org
Ajoutez le JSON-LD dans vos pages Next.js :
export default function ArticlePage({ article }) {
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'BlogPosting',
headline: article.title,
datePublished: article.publishedAt,
author: { '@type': 'Person', name: 'WebEngine' },
};
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<article>...</article>
</>
);
}
Sitemap et robots.txt dynamiques
Next.js 15 génère sitemap.xml et robots.txt automatiquement si vous créez les fichiers correspondants :
// app/sitemap.ts
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const articles = await getAllArticles();
return articles.map(a => ({
url: `https://votre-site.fr/blog/${a.slug}`,
lastModified: a.updatedAt,
changeFrequency: 'weekly',
priority: 0.8,
}));
}