Performance web et Lighthouse : atteindre le score 100
Un score Lighthouse de 100 n'est pas un but en soi — mais le comprendre force à corriger les vrais problèmes de performance. Voici comment lire les métriques et améliorer chacune.
Un score Lighthouse de 100 ne garantit pas que votre site est rapide. Il garantit qu'il passe tous les audits automatiques dans des conditions de laboratoire — réseau 4G simulé, CPU ralenti de 4×. C'est utile, mais différent des données terrain.
Ce que Lighthouse vous apporte concrètement : une liste de problèmes classés par impact, avec les corrections précises à apporter. C'est un guide de correction, pas une note définitive.
Accéder à Lighthouse
Dans Chrome DevTools :
F12 → onglet "Lighthouse" → Analyser la pageChoisir : Performance + Accessibilité + Bonnes pratiques + SEO. Mode Desktop ou Mobile (toujours tester les deux).
Via CLI (pour CI/CD) :
npm install -g lighthouse
# Audit basique
lighthouse https://iducation.fr --output html --output-path ./report.html
# Audit avec options
lighthouse https://iducation.fr \
--only-categories=performance,seo,accessibility \
--chrome-flags="--headless" \
--output json \
--output-path ./report.jsonPageSpeed Insights (pagespeed.web.dev) — combine Lighthouse (lab) + CrUX (terrain). À préférer pour les décisions SEO car il inclut les données réelles Chrome.
Les 4 catégories
| Catégorie | Ce qu'elle mesure |
|---|---|
| Performance | Vitesse de chargement (métriques lab) |
| Accessibilité | ARIA, contrastes, structure HTML |
| Bonnes pratiques | HTTPS, images modernes, console errors |
| SEO | Meta, title, robots.txt, liens crawlables |
Les métriques Performance expliquées
FCP — First Contentful Paint
Premier contenu visible (texte, image, canvas). Cible : < 1,8s.
Améliorer : éliminer les ressources render-blocking (CSS/JS critiques inline ou préchargés), réduire le TTFB.
LCP — Largest Contentful Paint
Plus grand élément visible. Cible : < 2,5s. Le signal le plus important pour l'expérience utilisateur.
<!-- Précharger l'image LCP -->
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high">
<img src="/hero.webp" alt="..." fetchpriority="high" width="1200" height="630">TBT — Total Blocking Time
Temps total pendant lequel le thread principal est bloqué (Long Tasks > 50ms) entre FCP et TTI. Cible : < 200ms. Corrélé à l'INP (données terrain).
// ❌ Long Task qui bloque l'UI
function processData(data) {
return data.map(item => heavyTransform(item)) // 300ms de blocage
}
// ✅ Découper en chunks
async function processDataChunked(data, chunkSize = 100) {
const results = []
for (let i = 0; i < data.length; i += chunkSize) {
const chunk = data.slice(i, i + chunkSize)
results.push(...chunk.map(item => heavyTransform(item)))
await new Promise(r => setTimeout(r, 0)) // Cède le thread
}
return results
}CLS — Cumulative Layout Shift
Stabilité visuelle. Cible : < 0,1.
/* Réserver l'espace pour les images avant leur chargement */
.image-container {
aspect-ratio: 16 / 9; /* Ou width/height directement sur <img> */
}Speed Index
Vitesse à laquelle le contenu visible se remplit visuellement. Cible : < 3,4s. Amélioré par la réduction du CSS render-blocking et l'optimisation du LCP.
Les audits Lighthouse les plus impactants
Éliminer les ressources render-blocking
<!-- ❌ CSS render-blocking -->
<link rel="stylesheet" href="/styles.css">
<!-- ✅ CSS critique inline + CSS non-critique asynchrone -->
<style>/* CSS critique pour above-the-fold */</style>
<link rel="preload" href="/styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<!-- ❌ JS render-blocking -->
<script src="/app.js"></script>
<!-- ✅ Différer le JS -->
<script src="/app.js" defer></script>
<!-- Ou async si le script est indépendant -->
<script src="/analytics.js" async></script>Images en formats modernes
# Convertir en WebP (cwebp)
cwebp -q 80 image.jpg -o image.webp
# Convertir en AVIF (avifenc)
avifenc image.jpg image.avif
# Script batch
for f in *.jpg; do cwebp -q 80 "$f" -o "${f%.jpg}.webp"; done<!-- <picture> pour servir le bon format selon le navigateur -->
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Description" width="800" height="450">
</picture>Voir le guide complet des images pour le SEO pour srcset, dimensions responsives et lazy loading.
Réduire le CSS inutilisé
# Avec PurgeCSS — supprimer le CSS non utilisé
npm install -D purgecss
# next.config.js — Tailwind le fait automatiquement en prodTailwind CSS avec Next.js purge automatiquement le CSS inutilisé en production — aucune configuration supplémentaire.
JavaScript non utilisé
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
const nextConfig = {
webpack: (config, { isServer }) => {
if (!isServer && process.env.ANALYZE === 'true') {
config.plugins.push(new BundleAnalyzerPlugin())
}
return config
},
}ANALYZE=true npm run buildIdentifier les modules trop lourds et les remplacer ou les lazy-loader.
Préconnexion aux origines critiques
<!-- Préconnecter aux domaines externes critiques -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="dns-prefetch" href="https://cdn.monsite.fr">TTFB — optimiser la réponse serveur
Le TTFB (Time To First Byte) n'est pas une métrique Lighthouse mais affecte toutes les autres. Lighthouse le signale comme "Server Response Time".
Cible : < 600ms.
Améliorations :
- Cache serveur (Redis, Nginx
proxy_cache) - CDN (Cloudflare, Vercel Edge Network)
- Génération statique (SSG) vs rendu à la demande (SSR)
- Configuration Nginx optimisée avec gzip et caching
Intégration dans le CI/CD
name: Lighthouse CI
on: [push]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Lighthouse CI
uses: treosh/lighthouse-ci-action@v11
with:
urls: |
https://iducation.fr
https://iducation.fr/articles
budgetPath: ./lighthouse-budget.json
uploadArtifacts: true[
{
"path": "/*",
"timings": [
{ "metric": "first-contentful-paint", "budget": 2000 },
{ "metric": "largest-contentful-paint", "budget": 2500 },
{ "metric": "cumulative-layout-shift", "budget": 0.1 },
{ "metric": "total-blocking-time", "budget": 300 }
],
"resourceSizes": [
{ "resourceType": "script", "budget": 300 },
{ "resourceType": "image", "budget": 500 }
]
}
]Le CI échoue si ces seuils sont dépassés — les régressions de performance sont bloquées avant d'atterrir en production.
Accessibilité dans Lighthouse
Le score Accessibilité Lighthouse teste automatiquement les règles WCAG les plus simples : contrastes de couleurs, labels de formulaires, attributs ARIA, ordre des headings.
Un score 100 en accessibilité Lighthouse ne signifie pas que votre site est accessible — les tests automatiques ne détectent que ~30% des problèmes WCAG. Le guide WCAG complet couvre les tests manuels indispensables que Lighthouse ne peut pas automatiser.
Score 100 — est-ce atteignable ?
Oui, sur des pages statiques simples. Sur des pages avec vidéos embarquées, widgets tiers, publicités programmatiques — difficile. Et ce n'est pas le but.
Le but : un score Performance ≥ 90 en mobile, Accessibilité ≥ 95, SEO 100. Ces seuils correspondent à une expérience utilisateur acceptable et à un site bien référencé.
Lighthouse est un point de départ, pas une fin. Les vraies données terrain (CrUX dans Search Console, web-vitals.js en production) sont ce qui compte pour le SEO et l'expérience réelle. Utilisez Lighthouse pour identifier les problèmes, et Search Console pour mesurer leur impact réel sur vos utilisateurs.