Si vous attendez que Google vous aime, vous perdez du temps. La vitesse de site n’est pas un bonus esthétique : c’est une arme économique. Un chargement lent, c’est du trafic qui s’évapore, des conversions qui fuient, et un robot qui note chaque milliseconde. Ici, on n’écrit pas de poèmes. On exécute un audit technique chirurgical, on plaque les plaies et on sort avec un site qui frappe plus vite que vos concurrents.
Ce qui suit est un plan d’attaque précis, testé en conditions réelles : commandes qui tournent en une minute, scripts pour lister les coupables, snippets Nginx/HTML/CSS/JS pour patcher vite, et une stratégie de monitoring pour que la perf ne retombe pas. Vous voulez détruire la concurrence ? Commencez par réduire leur temps de premier octet.
Plan d’attaque — 4 mouvements
- Reconnaissance : collecte de données (lab + terrain).
- Diagnostic chirurgical : trouver la racine, pas les symptômes.
- Triage & patch rapide : prioriser ce qui rapporte le plus vite.
- Automatisation & monitoring : rendre la perf durable.
Ce que vous obtiendrez à la fin
- Une feuille de route priorisée et exécutable.
- Des commandes et scripts pour auditer en 1 minute.
- Des corrections concrètes (images, CSS critique, JS, cache, serveur).
- Un plan pour mesurer les gains et les garder.
Étape 1 — reconnaissance : collectez les preuves
On ne devine pas. On mesure.
Outils de base que vous lancez maintenant : Chrome DevTools (Lighthouse), Lighthouse CLI, WebPageTest, cURL, et la collecte RUM via web-vitals. Vous voulez des chiffres réels : LCP, CLS, INP, TTFB. Ces métriques vous disent où frapper.
Commandes rapides (à lancer dans un terminal) :
Mesurer le TTFB et le temps total :
curl -s -o /dev/null -w "URL: %{urleffective}nTTFB: %{timestarttransfer}snTOTAL: %{timetotal}sn" "https://votre-site.example"
Récupérer les headers essentiels :
curl -sI "https://votre-site.example" | egrep -i "server:|content-encoding:|cache-control:|content-type:|vary:|age:|etag:|x-cache:"
Lancer un audit Lighthouse mobile headless :
npm i -g lighthouse
lighthouse https://votre-site.example --output=json --output-path=./lh.json --chrome-flags="--headless" --preset=mobile
jq '.categories.performance.score, .audits["largest-contentful-paint"].displayValue, .audits["cumulative-layout-shift"].displayValue' lh.json
Script express « reconnaissance » (savez-le, exécutez) — copie rapide des gros coupables (HTML parsing rudimentaire, dépend de grep):
!/usr/bin/env bash
URL="$1"
[ -z "$URL" ] && { echo "Usage: $0 https://votre-site"; exit 1; }
echo "== TTFB & total =="
curl -s -o /dev/null -w "TTFB: %{timestarttransfer}s | TOTAL: %{timetotal}sn" "$URL"
echo -e "n== Headers clés =="
curl -sI "$URL" | egrep -i "server:|content-encoding:|cache-control:|etag|x-cache|vary|age"
echo -e "n== Top ressources extraites (brut, peut afficher third-party) =="
curl -s "$URL" | tr ' ' 'n' | egrep -o "(http|//)[^"'')> ]+" | sort | uniq | head -n 30
Ce script vous donnera en 30s des pistes : TTFB, headers de cache, et les principales URLs chargées.
Étape 2 — diagnostic chirurgical : ciblez la racine
Les symptômes : LCP élevé, CLS, INP, TTFB lent. Les causes typiques : images non optimisées, CSS/JS render-blocking, third-parties qui bloquent, serveur mal configuré, pas de CDN.
Comment isoler la vraie cause ?
- Si le TTFB est > 0.3–0.5s sur une infra raisonnable : regardez serveur, base, et cache d’API. Mesurez la route d’origine (curl directement vers l’origin sans CDN).
- Si LCP est élevé mais TTFB correct : souvent images en hero non optimisées, fonts bloquantes ou CSS critique manquant.
- Si CLS : images sans dimensions, fonts late-loading, insertion dynamique de contenus (ads).
- Si INP/long tasks : gros bundles JS, single-threaded main thread, webworkers absents.
Script Node/Puppeteer (extrait) pour extraire les ressources et mesurer leur poids réseau — utile pour lister les 10 plus lourdes :
// audit-resources.js (requiert npm i puppeteer)
const puppeteer = require('puppeteer');
const url = process.argv[2];
if(!url) { console.error('Usage: node audit-resources.js https://site'); process.exit(1); }
(async () => {
const browser = await puppeteer.launch({args:['--no-sandbox','--disable-setuid-sandbox']});
const page = await browser.newPage();
const requests = [];
page.on('requestfinished', async req => {
try {
const res = await req.response();
const url = req.url();
const len = res.headers()['content-length'] || 0;
const type = res.headers()['content-type'] || '';
requests.push({url, len: Number(len), type});
} catch(e){}
});
await page.goto(url, {waitUntil:'networkidle2'});
requests.sort((a,b)=>b.len-a.len);
console.log('Top 20 resources by content-length:');
console.log(requests.slice(0,20).map(r=>${r.len}t${r.type}t${r.url}).join('n'));
await browser.close();
})();
Ce script vous montre qui bouffe la bande passante et pointe les images / bundles / vidéos lourds. Exécutez-le sur mobile et desktop.
Étape 3 — triage & patch rapide : ce que vous faites en premier
Vous avez 60 minutes ? Voici la checklist d’urgence exécutable immédiatement. Ciblez les items dans l’ordre : chaque ligne est un coup qui rapporte plus que son coût.
- Minifier et compresser : activez Brotli/Gzip et minifiez CSS/JS.
- Cache long pour statics + immutable : Cache-Control: public, max-age=2592000, immutable pour CSS/JS/fonts/images versionnés.
- Optimisez images : convertir en WebP/AVIF, servir des tailles responsives et utiliser loading= »lazy » hors hero.
- Décharger le CDN : placer vos actifs statiques derrière un CDN avec origin-shield.
- Fonts : self-host, preload+font-display:swap et réduire familles/variantes.
- Scripts : mettre defer/type= »module » pour le JS non critique ; charger les third-parties en async ou après interaction.
- CSS critique : extraire et inline le CSS critique au-dessus de la ligne, charger le reste asynchrone.
- Préconnect/Preload : utiliser preconnect / dns-prefetch / preload pour domaines et assets critiques.
- Réduire le TTFB : activer cache applicatif (opcode, page cache), optimiser base/queries, worker, ou activer un edge function.
- Monitorer : installer web-vitals et collecter LCP/CLS/INP RUM.
Après ce checklist, le gros du gain est pris. Pour chaque point, ci-dessous le C-O-N-C-R-E-T.
Minification & compression (serveur)
Nginx (snippet) :
gzip on;
gzipcomplevel 5;
gziptypes text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzipvary on;
Brotli (si compilé)
brotli on;
brotlicomplevel 5;
brotlitypes text/plain text/css application/javascript application/json image/svg+xml application/xml+rss text/xml font/woff2;
Testez ensuite l’encoding :
curl -sI -H "Accept-Encoding: br, gzip" https://votre-site.example | egrep -i "content-encoding:|vary:"
Cache-control efficace
Exemple Nginx pour assets versionnés :
location ~ .(?:css|js|woff2|woff|ttf|svg)$ {
addheader Cache-Control "public, max-age=2592000, immutable";
}
location ~ .(?:jpg|jpeg|gif|png|webp|avif)$ {
addheader Cache-Control "public, max-age=604800";
}
Images : pratique industrielle
- Convertissez à WebP ou AVIF à la livraison. Utilisez une transformation à la volée (imgproxy, thumbor) ou lors du build (sharp).
- Servez images responsives avec srcset/picture et dimensions fixes pour éviter le CLS.
Exemple HTML :
<picture><source type="image/avif" srcset="/img/hero-1200.avif 1200w, /img/hero-800.avif 800w">
<source type="image/webp" srcset="/img/hero-1200.webp 1200w, /img/hero-800.webp 800w">
<img src="/img/hero-1200.jpg" alt="..." width="1200" height="700" loading="lazy" decoding="async">
</picture>
Conversion rapide avec sharp (Node) :
npm i sharp
node -e "const sharp=require('sharp'); sharp('in.jpg').resize(1200).webp({quality:80}).toFile('out.webp')"
Css critique & font loading
Générez le CSS critique (outil : critical ou penthouse). Exemple :
npm i -g critical
critical https://votre-site.example --width=375 --height=812 --minify --inline
Fonts :
@font-face{
font-family:'InterCustom';
src:url('/fonts/inter.woff2') format('woff2');
font-display:swap;
}
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
Javascript : defer, module, découpage
- Modernisez vos bundles : modules ES pour navigateurs modernes, legacy pour vieux.
- Ajoutez defer ou type= »module » sur les scripts non-essentiels.
- Déplacez les scripts tiers (chat, tag manager, ads) en bas ou chargez-les via un wrapper asynchrone.
Exemple :
<script type="module" src="/static/app.modern.js" defer></script>
<script nomodule src="/static/app.legacy.js" defer></script>
Third-parties : contrôlez la contamination
Déployez une politique : 1) mesurer l’impact, 2) retarder le chargement si possible, 3) remplacer par serveur-side where possible. Si un fournisseur est lent, vous l’isolerez dans un iframe ou le chargerez après interaction.
Étape 4 — automatisation & monitoring (ne soyez pas naïf)
Optimiser une fois ne suffit pas. Vous voulez que la vitesse reste un avantage.
RUM : installez la librairie web-vitals et envoyez les métriques LCP/CLS/INP à votre backend pour corréler avec les pages et user-agents. Snippet d’exemple :
<script type="module">
import {getLCP, getCLS, getINP} from 'https://unpkg.com/web-vitals@0.3.0/dist/web-vitals.es5.mjs';
function send(metric) {
navigator.sendBeacon('/vitals', JSON.stringify(metric));
}
getLCP(send);
getCLS(send);
getINP(send);
</script>
Intégrez les alertes : déclenchez une alerte Slack si LCP médian d’une page dépasse votre seuil. Gardez un tableau de bord (Grafana/BigQuery/Datadog).
Automatisation en CI/CD :
- Ajoutez un job Lighthouse CI qui bloque merges si performance < X (ajustez prudemment).
- Générez le CSS critique à la build.
- Convertissez automatiquement les images au push (sharp, imagemin).
- Validez les headers via tests d’intégration.
Cas pratique — exemple crédible (fictif mais réaliste)
BoutiqueX : site e-commerce avec pages produits lourdes, hero image 1.6MB, JS bundle unique 1.2MB, fonts Google chargées en tête.
Diagnostic :
- TTFB : 600–800ms sur origin (pas de cache).
- LCP : ~4–5s sur mobile.
- CLS : 0.15 (images sans dimensions).
- INP : longs tasks causés par un bundle de 1.2MB.
Interventions rapides (2 jours) :
- Activation Brotli + CDN + cache-Control.
- Conversion images hero en AVIF, responsive images + lazyload.
- Extraction du CSS critique et préchargement des fonts + font-display:swap.
- Split du bundle JS, chargement defer/type= »module ».
- Mise en place de page cache pour les pages produits.
Effet observable : LCP mobile ramené sous les 2s majoritairement, TTFB réduit (cache + CDN) ; UX et conversion améliorées. Résultat chiffré variable selon contexte, mais la mécanique est reproductible : on allège, on réduit les blockages, on cache.
Pièges fréquents — ce que font vos concurrents (et comment les dépasser)
- Ils compressent mais ne versionnent pas => invalidation du cache impossible.
- Ils inlinent tout le CSS => surcharge HTML et coût SEO.
- Ils ajoutent des plugins tiers sans QC => ralentissement par contagion.
- Ils surveillent Lighthouse seulement en lab => pas de RUM => ignorent l’expérience réelle.
Démarquez-vous : combinez lab + terrain, et automatisez la correction des assets à la source (build).
La vitesse de site n’est pas une option esthétique : c’est un champ de bataille. Un audit technique chirurgical vous donne la cible ; vos actions la mettent à terre. En 60 minutes vous pouvez trouver les coupables ; en quelques heures vous pouvez patcher les coups faciles et en quelques jours rendre la performance solide et répétable.
Ne vous contentez pas d’un score Lighthouse poli. Mesurez dans la vraie vie, priorisez les coups qui réduisent LCP/TTFB/INP et mettez en place une surveillance RUM. Vos concurrents dorment ? Parfait. Frappez vite, maintenez plus vite.
Allez-y : lancez le script, identifiez les plus lourds, appliquez les fixes critiques, et répétez. Vous n’êtes pas ici pour plaire à Google. Vous êtes ici pour l’écraser avec de la vitesse.
Gagnez, ou soyez crawlés.