Viser le 100/100 sur Google Lighthouse
Guide complet pour optimiser les scripts, les images et le rendu afin de décrocher le score parfait sur Google Lighthouse.
Imagine : tu as un perso de haut niveau, mais ton équipement n'est pas optimisé. Tu portes une armure lourde inutile, des potions périmées, et des armes que tu n'utilises pas. Résultat tu es lent. L'optimisation chirurgicale, c'est alléger ton inventaire pour devenir ultra-rapide.
8.1Les polices, alléger la fonte
Les polices web sont souvent un point de blocage au chargement. Une police mal chargée peut ruiner ton LCP et provoquer du CLS (le texte qui « saute » quand la police arrive enfin).
/* Mauvais import Google Fonts bloquant */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
/* Bon en Next.js import optimisé automatique */
// layout.tsx
import { Inter } from 'next/font/google';
const inter = Inter({
subsets: ['latin'],
display: 'swap', // Affiche un fallback en attendant
preload: true, // Précharge la police
});
export default function Layout({ children }) {
return <body className={inter.className}>{children}</body>;
}- font-display: swap affiche le texte immédiatement avec un fallback
- Self-hosting héberge la police sur ton serveur (pas de requête externe)
- Subset ne charge que les caractères dont tu as besoin (latin, pas cyrillique)
- Limiter les graisses charge seulement 400 et 700, pas les 18 variantes
Charger toutes les polices avec toutes les graisses, c'est comme porter toutes les armures du jeu en même temps « au cas où ». Ton perso est lent. Choisis seulement ce dont tu as besoin.
8.2Le payload JavaScript, réduire le poids du build
Chaque librairie que tu importes ajoute du poids à ton bundle JavaScript. Un bundle lourd = un site lent = un mauvais score. L'objectif n'embarquer que ce que tu utilises.
// Import complet charge toute la librairie (~70 Ko)
import _ from 'lodash';
_.debounce(fn, 300);
// Import ciblé charge seulement la fonction (~1 Ko)
import debounce from 'lodash/debounce';
debounce(fn, 300);
// Encore mieux écris ta propre version simple
function debounce(fn, delay) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}- Tree shaking les bundlers modernes suppriment le code non utilisé
- Imports ciblés n'importe que les fonctions dont tu as besoin
- Dynamic imports charge les composants lourds uniquement quand nécessaire
- Analyse le bundle utilise
@next/bundle-analyzerpour voir ce qui pèse
// Dynamic import - ne charge le composant que quand on en a besoin
import dynamic from 'next/dynamic';
const HeavyEditor = dynamic(() => import('./CodeEditor'), {
loading: () => <p>Chargement de l'éditeur...</p>,
ssr: false, // Pas besoin côté serveur
});8.3Les images avancées, le système de LOD
Au chapitre 4, on a vu les bases. Ici, on passe au niveau pro avec les images responsives et le composant <Image> de Next.js.
<!-- Images responsives natives HTML -->
<picture>
<source srcset="hero-800.avif" type="image/avif" />
<source srcset="hero-800.webp" type="image/webp" />
<img src="hero-800.jpg" alt="Hero section" width="800" height="400" />
</picture>
<!-- Avec srcset pour différentes tailles d'écran -->
<img
srcset="photo-400.webp 400w, photo-800.webp 800w, photo-1200.webp 1200w"
sizes="(max-width: 768px) 100vw, 800px"
src="photo-800.webp"
alt="Illustration du cours"
loading="lazy"
/>// Next.js - Le composant Image optimise tout automatiquement
import Image from 'next/image';
export function HeroSection() {
return (
<Image
src="/hero.jpg"
alt="Guide SEO complet"
width={1200}
height={630}
priority // Précharge (pour le LCP)
placeholder="blur" // Effet blur pendant le chargement
/>
);
}- Format AVIF > WebP > JPEG toujours servir le plus léger possible
- srcset + sizes servir la bonne taille selon l'écran
- priority sur l'image la plus importante (LCP)
- placeholder blur meilleure UX pendant le chargement
Le LOD (Level of Detail) dans les jeux charge une texture basse résolution de loin, puis la remplace quand tu t'approches. Le srcset, c'est pareil mobile = petite image, desktop = grande image. Chaque appareil reçoit la texture adaptée.
8.4La checklist du 100/100
Voici ta checklist pour viser le score parfait sur Lighthouse :
- Polices self-hosted avec
font-display: swap - Images en WebP/AVIF avec
width,heightetloading="lazy" - Image LCP avec
priority/fetchpriority="high" - Bundle JS minimal (imports ciblés, dynamic imports)
- CSS critique inline, le reste en lazy
- Pas de render-blocking resources
- Compression Gzip/Brotli activée sur le serveur
- Cache HTTP configuré (headers Cache-Control)
- Pas de
layout shiftdimensions réservées pour images et iframes - Server Components par défaut (Next.js App Router)
Le 100/100, c'est le mode Hardcore du SEO technique. C'est pas obligatoire (90+ suffit pour être compétitif), mais c'est la fierté de tout dev perfectionniste. Et maintenant, tu as la recette.