Images, Fonts & Metadata
Optimise tout ce qui rend ton site beau et visible sur Google.
7.1next/image : des images intelligentes
Le composant Image de Next.js remplace la balise <img> classique. Il fait tout ce que tu devrais faire toi-même mais que personne ne fait :
- Compression automatique : tes images de 5 Mo deviennent légères sans perdre en qualité.
- Lazy loading : les images ne se chargent que quand elles arrivent dans le viewport.
- Taille adaptée : l'image servie est dimensionnée pour l'écran du visiteur.
- Format moderne : conversion en WebP ou AVIF automatiquement.
- Pas de CLS : l'espace est réservé avant le chargement (pas de saut de page).
import Image from 'next/image'
export default function ProfilPage() {
return (
<div>
{/* Image locale (dans /public) */}
<Image
src="/photo-profil.jpg"
alt="Ma photo de profil"
width={300}
height={300}
/>
{/* Image distante */}
<Image
src="https://example.com/photo.jpg"
alt="Photo externe"
width={800}
height={400}
/>
</div>
)
}// next.config.ts
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
},
],
},
}
export default nextConfig7.2Image en fill : remplir un conteneur
Parfois tu ne connais pas les dimensions exactes de l'image (avatar dynamique, image d'un CMS...). Utilise le mode fill :
<div className="relative w-full h-64">
<Image
src="/hero-banner.jpg"
alt="Bannière"
fill
className="object-cover rounded-xl"
/>
</div>L'image remplit son conteneur parent (qui doit être en position: relative). Avec object-cover, elle crop proprement sans se déformer. Parfait pour les bannières et les cards.
7.3next/font : des polices sans clignotement
Tu connais ce moment agaçant où la page charge avec une police par défaut, puis "saute" quand la vraie police arrive ? Next.js élimine ce problème avec next/font.
// app/layout.tsx
import { Inter, Fira_Code } from 'next/font/google'
const inter = Inter({
subsets: ['latin'],
variable: '--font-inter',
})
const firaCode = Fira_Code({
subsets: ['latin'],
variable: '--font-fira-code',
})
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="fr" className={`${inter.variable} ${firaCode.variable}`}>
<body className="font-sans">
{children}
</body>
</html>
)
}Les avantages :
- Zero layout shift : la police est intégrée au build, pas téléchargée après coup.
- Self-hosted : pas de requête vers Google Fonts. Mieux pour la vie privée et la vitesse.
- Variables CSS : tu peux utiliser la police partout via
var(--font-inter).
7.4Metadata : le SEO en pilote automatique
Les métadonnées (titre, description, Open Graph...) sont essentielles pour que Google comprenne ta page et pour avoir de beaux previews sur les réseaux sociaux.
Next.js te propose deux façons de les définir :
Metadata statique (le plus courant)
// app/layout.tsx ou n'importe quelle page
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: {
default: 'Mon Super Site',
template: '%s | Mon Super Site', // Les sous-pages héritent
},
description: 'Le meilleur site du monde pour apprendre Next.js',
openGraph: {
title: 'Mon Super Site',
description: 'Apprenez Next.js facilement',
images: ['/og-image.png'],
},
}Metadata dynamique (par page)
// app/blog/[slug]/page.tsx
import type { Metadata } from 'next'
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>
}): Promise<Metadata> {
const { slug } = await params
const article = await getArticle(slug)
return {
title: article.title,
description: article.excerpt,
openGraph: {
images: [article.coverImage],
},
}
}Avec generateMetadata, chaque page a son propre titre et sa propre description. Google adore ça.
7.5Héritage des métadonnées
Les métadonnées fonctionnent comme les layouts : elles s'héritent et se fusionnent du layout racine vers les sous-pages.
app/
├── layout.tsx # title: "Mon Site" (défaut global)
├── blog/
│ ├── layout.tsx # description: "Tous mes articles"
│ └── [slug]/
│ └── page.tsx # title: "Mon Article" → affiche "Mon Article | Mon Site"Grâce au template: '%s | Mon Super Site', les sous-pages affichent automatiquement leur titre suivi du nom du site. Pas besoin de le répéter partout.