Cache HTTP : cache fort, cache négocié et stratégies CDN

Web/SEO

Cache HTTP : la première ligne de défense de l'optimisation des performances

Une configuration de cache appropriée permet zéro requête réseau au deuxième accès, réduisant le temps de chargement de secondes à millisecondes.

Type de cache Mécanisme Requête au serveur ? Vitesse
Cache fort Cache-Control / Expires Non La plus rapide (0ms)
Cache négocié ETag / Last-Modified Oui (requête conditionnelle) Rapide (réponse 304)
Pas de cache no-cache / no-store Oui (requête complète) La plus lente

I. Cache fort

Directives Cache-Control

Cache-Control: max-age=31536000, immutable
Directive Fonction Scénario applicable
max-age=N Mettre en cache N secondes Ressources statiques
s-maxage=N CDN met en cache N secondes (remplace max-age) Scénarios CDN
immutable Ne pas revalider même si expiré Noms de fichiers avec hachage
public Autoriser le cache intermédiaire CDN
private Cache du navigateur uniquement Contenu personnalisé
no-cache Doit valider avant chaque utilisation Pages HTML
no-store Ne rien mettre en cache Données sensibles
must-revalidate Doit valider après expiration Réponses API
stale-while-revalidate=N Retourner l'ancienne valeur après expiration, actualiser en arrière-plan Mise à jour progressive

Expires (ancien standard)

Expires: Thu, 02 Jun 2027 00:00:00 GMT

Priorité : Cache-Control: max-age > Expires.


II. Cache négocié

ETag / If-None-Match

# Première requête
GET /api/data
→ 200 OK
  ETag: "abc123"
  Cache-Control: max-age=0

# Requête suivante (conditionnelle)
GET /api/data
If-None-Match: "abc123"
→ 304 Not Modified  (sans corps de réponse, économise la bande passante)

Last-Modified / If-Modified-Since

# Première requête
GET /style.css
→ 200 OK
  Last-Modified: Mon, 01 Jun 2026 12:00:00 GMT

# Requête suivante
GET /style.css
If-Modified-Since: Mon, 01 Jun 2026 12:00:00 GMT
→ 304 Not Modified

ETag vs Last-Modified

Dimension ETag Last-Modified
Précision Niveau octet Niveau seconde
Performance Nécessite un calcul de hachage Lecture directe de l'heure du fichier
Fiabilité Élevée Faible (modifications multiples en 1 seconde perdues)
Distribué Doit garantir un hachage cohérent Naturellement cohérent

Recommandation : Prioriser ETag.


III. Matrice des stratégies de cache

Pages HTML

Cache-Control: no-cache

HTML est le fichier d'entrée, doit être validé à chaque fois pour s'assurer que les utilisateurs obtiennent la dernière version.

Ressources statiques avec hachage

Cache-Control: max-age=31536000, immutable

Le nom du fichier contient un hachage (ex., app.abc123.js), quand le contenu change, le hachage change → l'URL change → nouvelle requête. L'ancienne URL ne change jamais, peut être mise en cache un an et marquée immutable.

Ressources statiques sans hachage

Cache-Control: max-age=86400, stale-while-revalidate=604800

Après expiration, retourne d'abord l'ancienne valeur, actualise silencieusement en arrière-plan, imperceptible pour l'utilisateur.

Réponses API

Cache-Control: private, max-age=0, must-revalidate

Les réponses API contiennent généralement des données utilisateur, private interdit le cache CDN, must-revalidate garantit qu'aucune valeur ancienne n'est retournée après expiration.


IV. En-tête Vary : extension de la clé de cache

Vary: Accept-Encoding, Accept-Language

Vary indique au cache : en plus de l'URL, distinguer les versions de cache selon les valeurs de ces en-têtes de requête.

Valeur Vary Signification Scénario
Accept-Encoding Cacher par méthode de compression gzip vs br
Accept-Language Cacher par langue Sites multilingues
Cookie Cacher par Cookie Pages personnalisées
* Chaque requête avec cache indépendant Équivaut à pas de cache

Attention : Vary: Cookie entraîne un taux de réussite de cache très faible, à utiliser avec précaution.


V. Stratégie de cache CDN

Contrôle de récupération d'origine

# CDN met en cache 1 jour, navigateur met en cache 5 minutes
Cache-Control: public, s-maxage=86400, max-age=300
Scénario s-maxage max-age Description
Ressources statiques 31536000 31536000 CDN et navigateur avec cache long
Réponses API 300 0 CDN met en cache 5 minutes, navigateur ne met pas en cache
HTML 60 0 CDN met en cache 1 minute, navigateur ne met pas en cache
Contenu personnalisé — 0 CDN ne met pas en cache, navigateur ne met pas en cache

Actualisation du cache CDN

Méthode Vitesse Applicable
Préchauffage d'URL Rapide Nouveau contenu en ligne
Actualisation complète Lent Correction urgente
Actualisation de répertoire Moyen Mise à jour par lot
Cache-Control: no-cache Automatique Scénarios API

Stale-While-Revalidate en pratique

Cache-Control: max-age=60, stale-while-revalidate=86400
Seconde 0 : Requête → Cache MISS → Récupération d'origine → Retourne valeur fraîche
Seconde 30 : Requête → Cache HIT → Retourne valeur en cache
Seconde 90 : Requête → Cache STALE → Retourne ancienne valeur immédiatement + récupération d'origine en arrière-plan
Seconde 91 : Récupération d'origine terminée → Cache mis à jour
Seconde 120 : Requête → Cache HIT → Retourne nouvelle valeur

Effet : L'utilisateur n'attend jamais la récupération d'origine, mise à jour silencieuse en arrière-plan.


VI. Stratégie d'invalidation du cache

Hachage de contenu (recommandé)

<!-- Hachage généré à la compilation -->
<script src="/app.abc123.js"></script>
<link href="/style.def456.css">
// Configuration webpack
output: {
  filename: '[name].[contenthash:8].js',
}

Paramètre de requête de version

<!-- Simple mais le CDN peut ne pas cacher les paramètres ?v= -->
<script src="/app.js?v=2.0.0"></script>

Problème : Certains CDN ignorent les paramètres de requête, empêchant la mise à jour du cache.

Horodatage (non recommandé)

<!-- Change à chaque fois, détruit complètement le cache -->
<script src="/app.js?t=1717315200"></script>

VII. Cache Service Worker

Stratégie Cache First

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request)
      .then(cached => cached || fetch(event.request))
  );
});

Stratégie Stale While Revalidate

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.open('dynamic').then(cache =>
      cache.match(event.request).then(cached => {
        const fetchPromise = fetch(event.request)
          .then(response => {
            cache.put(event.request, response.clone());
            return response;
          });
        return cached || fetchPromise;
      })
    )
  );
});

Sélection de la stratégie de cache

Stratégie Source prioritaire Applicable
Cache First Cache Polices, images
Network First Réseau API, HTML
Stale While Revalidate Cache + mise à jour en arrière-plan CSS, JS
Network Only Réseau Requêtes non-GET
Cache Only Cache Pages hors ligne

VIII. Débogage du cache

Chrome DevTools

  1. DevTools → Panneau Network
  2. Vérifier la colonne Size :
    • from disk cache : Succès du cache disque
    • from memory cache : Succès du cache mémoire
    • Taille réelle : Échec
  3. Vérifier l'en-tête de réponse Age : Temps passé en cache
  4. Cocher Disable cache : Désactiver le cache (quand DevTools est ouvert)

Vérification avec curl

# Voir les en-têtes de réponse
curl -I https://example.com/style.css

# Envoyer une requête conditionnelle
curl -I -H 'If-None-Match: "abc123"' https://example.com/style.css
# 304 indique un succès du cache négocié

# Simuler un autre Accept-Encoding
curl -I -H 'Accept-Encoding: br' https://example.com/style.css

IX. Liste des meilleures pratiques

  1. HTML : no-cache, garantir que l'entrée est toujours à jour
  2. JS/CSS avec hachage : max-age=1 an + immutable
  3. API : must-revalidate, doit valider après expiration
  4. CDN : s-maxage pour contrôler la fréquence de récupération d'origine
  5. Vary : Accept-Encoding, distinguer les méthodes de compression
  6. Utiliser ETag plutôt que Last-Modified
  7. stale-while-revalidate pour une mise à jour imperceptible
  8. Service Worker pour compléter les capacités hors ligne
#HTTP缓存#Cache-Control#ETag#CDN#性能优化