Optimiser la performance HTTP
Ce guide s'adresse a quelqu'un qui administre deja un serveur Apache et veut reduire le poids transfere et la latence percue, avec des verifications reproductibles. Chaque section est autonome : appliquez ce dont vous avez besoin.
Remplacez <VOTRE_DOMAINE> par votre domaine reel dans toutes les commandes.
Choix par defaut assumes ici :
- HTTP/2 (HTTP/3 optionnel, non couvert)
- Compression Brotli avec repli Gzip
- Cache long uniquement pour les assets versionnes (hash dans le nom)
- Pas de CDN (les en-tetes restent valables si vous en ajoutez un)
1. Activer Brotli avec repli Gzip
Objectif : servir Brotli aux clients qui l'acceptent, Gzip aux autres, et ne jamais compresser deux fois.
Creez une conf de compression dediee (ex. conf-available/compression.conf) :
<IfModule mod_headers.c> # Cache correct des variantes compressees / non compressees Header append Vary "Accept-Encoding" </IfModule> # Marque les requetes qui acceptent Brotli (token "br" dans Accept-Encoding) SetEnvIfNoCase Accept-Encoding "(?:^|,|\s)br(?:\s*;q=[0-9.]+)?(?:,|$)" prefer_brotli=1 <IfModule mod_brotli.c> AddOutputFilterByType BROTLI_COMPRESS \ text/html text/plain text/css application/javascript application/json image/svg+xml \ env=prefer_brotli # Niveau 5 : bon compromis CPU / ratio de compression BrotliCompressionQuality 5 </IfModule> <IfModule mod_deflate.c> # Ne pas appliquer Gzip quand Brotli est retenu RemoveOutputFilter DEFLATE \ text/html text/plain text/css application/javascript application/json image/svg+xml \ env=prefer_brotli # Repli Gzip pour les clients sans "br" AddOutputFilterByType DEFLATE \ text/html text/plain text/css application/javascript application/json image/svg+xml </IfModule>
Activez, testez la syntaxe, rechargez :
sudo a2enmod brotli sudo a2enconf compression sudo apache2ctl -t && sudo systemctl reload apache2
Neutraliser le deflate.conf par defaut
Sur Debian/Ubuntu, le fichier deflate.conf du module active souvent DEFLATE sur text/html et d'autres types. Cela peut forcer Gzip meme quand le client accepte Brotli. Commentez ces lignes AddOutputFilterByType DEFLATE ... par defaut et laissez la gestion Gzip uniquement dans votre compression.conf :
# A commenter dans le deflate.conf du module # AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript # AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript # AddOutputFilterByType DEFLATE application/rss+xml application/xml application/wasm
Puis rechargez : sudo apache2ctl -t && sudo systemctl reload apache2.
Verifier la negociation d'encodage
Utilisez GET (-o /dev/null -D -), pas HEAD (curl -I) qui peut etre trompeur sur la compression.
# Brotli attendu -> Content-Encoding: br curl -sS --http2 -H "Accept-Encoding: br" -o /dev/null -D - https://<VOTRE_DOMAINE>/ # Repli Gzip attendu -> Content-Encoding: gzip curl -sS --http2 -H "Accept-Encoding: gzip" -o /dev/null -D - https://<VOTRE_DOMAINE>/ # Aucun encodage attendu -> pas de Content-Encoding curl -sS --http2 -H "Accept-Encoding: identity" -o /dev/null -D - https://<VOTRE_DOMAINE>/ # Navigateur moderne : Brotli doit gagner si la priorite est correcte curl -sS --http2 -H "Accept-Encoding: gzip, deflate, br, zstd" \ -o /dev/null -D - https://<VOTRE_DOMAINE>/
Comparez les tailles pour confirmer le gain (attendu : br < gzip < identity) :
curl -s -H "Accept-Encoding: br" -w "br_size=%{size_download}\n" -o /dev/null https://<VOTRE_DOMAINE>/chemin.css curl -s -H "Accept-Encoding: gzip" -w "gz_size=%{size_download}\n" -o /dev/null https://<VOTRE_DOMAINE>/chemin.css
Ne compressez pas les formats deja compresses (jpg, png, webp, pdf) : le gain est nul et le CPU gaspille. La config ci-dessus les exclut deja.
2. Cache navigateur pour les assets statiques
Reservez le cache immuable aux fichiers dont le nom contient un hash de build (leur URL change a chaque modification, donc aucun risque de servir une version perimee).
<IfModule mod_headers.c> <FilesMatch "\.(css|js|svg)$"> Header set Cache-Control "public, max-age=31536000, immutable" </FilesMatch> </IfModule>
Activez et rechargez comme en section 1 (a2enconf, puis test + reload).
Verifiez les en-tetes et la revalidation 304 :
curl -I https://<VOTRE_DOMAINE>/build/app.css | egrep -i "^(cache-control|etag|last-modified):" ETAG=$(curl -sI https://<VOTRE_DOMAINE>/favicon.svg | awk -F': ' '/^etag:/ {print $2}') curl -I -H "If-None-Match: $ETAG" https://<VOTRE_DOMAINE>/favicon.svg # Attendu : HTTP/2 304 (pas de re-telechargement)
Si vous saisissez l'ETag a la main, pensez a echapper les guillemets qui l'entourent.
3. Confirmer le Vary: Accept-Encoding
Indispensable des qu'un cache intermediaire (proxy, CDN) existe, pour ne pas servir une reponse compressee a un client qui ne l'accepte pas.
curl -I https://<VOTRE_DOMAINE>/ | grep -i "^vary:" # Attendu : Vary: Accept-Encoding
S'il manque, ajoutez-le pour les types compresses via Header append Vary "Accept-Encoding" (deja present dans la conf de la section 1).
4. Verifier la reutilisation de connexion (Keep-Alive)
Deux requetes successives : la seconde doit etre plus rapide, la connexion et le handshake TLS etant reutilises.
curl -sw "\n%{time_starttransfer} %{time_total}\n" -o /dev/null https://<VOTRE_DOMAINE>/; \ curl -sw "\n%{time_starttransfer} %{time_total}\n" -o /dev/null https://<VOTRE_DOMAINE>/
5. Confirmer HTTP/2
curl -I --http2 https://<VOTRE_DOMAINE>/ -w "\nhttp/%{http_version}\n" -o /dev/null # Attendu : http/2
6. Test de charge legere (sanity)
Un tir court pour verifier qu'il n'y a pas d'erreurs ni de latence anormale. Calibrez les seuils selon votre machine.
ab -n 500 -c 50 https://<VOTRE_DOMAINE>/
Attendus : taux d'erreurs proche de zero, latences p95/p99 raisonnables. En cas de degradation, revenez sur les sections precedentes (compression, cache) avant d'incriminer le serveur.
7. OCSP Stapling (latence TLS)
Le stapling evite au client d'interroger l'autorite de certification pendant le handshake. Verification rapide :
openssl s_client -connect <VOTRE_DOMAINE>:443 -servername <VOTRE_DOMAINE> -status < /dev/null \ | grep -A3 "OCSP Response Status" # Attendu : OCSP Response Status: successful
La mise en place du stapling releve de la configuration TLS de votre serveur (hors perimetre de ce guide).