Cache-Control — qu’est-ce que c’est, directives et gestion du cache

Auteur : IT Sectr Publié le : 2026-03-09 Temps de lecture : 9 min

Cache-Control est un en-tête HTTP qui définit les règles de mise en cache des ressources côté client, serveurs proxy et CDN à l’aide d’un ensemble de directives. Contrairement à l’en-tête obsolète Expires, Cache-Control prend en charge des dizaines de combinaisons : max-age définit la durée de vie en secondes, private et public contrôlent la disponibilité du cache, no-cache et no-store — vérification forcée. Selon Google Web Dev (2025), une configuration correcte de Cache-Control peut réduire le temps de chargement des pages de 50 à 80 % pour les visites répétées. Cela rend l’en-tête crucial pour les performances des applications Web et mobiles.

Points clés

  • Cache-Control — un en-tête HTTP avec des directives qui contrôlent la mise en cache sur le client, le proxy et le CDN
  • max-age — une directive clé qui définit la durée de vie de la ressource en secondes sans revalidation
  • private vs public — private autorise le cache uniquement sur le client, public également sur les proxy et CDN
  • no-cache vs no-store — no-cache exige une validation avant utilisation, no-store interdit complètement la mise en cache
  • s-maxage — remplace max-age pour les caches partagés sans affecter les navigateurs

Qu’est-ce que Cache-Control ?

Cache-Control est un en-tête HTTP, normalisé dans HTTP/1.1 (RFC 7234), qui permet au serveur de spécifier comment et pendant combien de temps les clients, les proxy et les CDN peuvent mettre en cache la réponse. Contrairement à Expires (HTTP/1.0), Cache-Control utilise des directives — des commandes textuelles combinées avec des virgules : Cache-Control: public, max-age=3600, must-revalidate. L’en-tête offre un contrôle précis sur chaque maillon de la chaîne de mise en cache.

La mise en cache est l’un des mécanismes fondamentaux des performances des applications Web et mobiles. Sans elle, chaque requête utilisateur irait directement au serveur, provoquant une charge excessive et de la latence. Cache-Control définit trois niveaux de cache : navigateur/application (cache privé), serveurs proxy (cache partagé) et CDN (cache distribué). Chaque niveau interprète les directives différemment.

Une configuration incorrecte de Cache-Control est l’une des causes les plus courantes de problèmes de performance. Un cache trop agressif fait que les utilisateurs voient des données obsolètes. Un cache trop faible entraîne des requêtes excessives au serveur et un chargement lent. Selon Akamai (2025), l’optimisation de Cache-Control pour le contenu statique réduit la charge du serveur de 70 à 90 % et améliore le temps de chargement de 40 à 60 % pour les utilisateurs mobiles.

Historique de l’en-tête

Cache-Control est apparu dans HTTP/1.1 (RFC 2616, 1999) en remplacement d’Expires. Expires avait un problème fondamental : il utilisait une date absolue qui dépendait des fuseaux horaires du serveur et du client. Cache-Control a résolu ce problème en passant au temps relatif (max-age en secondes à partir du moment de la réception de la réponse). Plus tard, dans RFC 7234 (2014), de nouvelles directives ont été ajoutées : immutable pour les ressources statiques, stale-while-revalidate et stale-if-error pour la validation différée.

Directives de Cache-Control

Cache-Control comprend plus de 10 directives réparties en trois groupes : les directives de requête (client → serveur), les directives de réponse (serveur → client) et les extensions. En pratique, le développement mobile utilise 6 à 7 directives de réponse principales qui couvrent 95 % des scénarios de cache. Examinons chacune avec des exemples et des recommandations.

DirectiveSignificationExemple
max-ageDurée de vie en secondes à partir de la réponsemax-age=3600 — 1 heure
s-maxagemax-age pour le cache partagé (proxy, CDN)s-maxage=86400 — 1 jour pour CDN
publicAutorise la mise en cache par tous (y compris les proxy)public, max-age=3600
privateAutorise le cache uniquement pour le navigateur/l’applicationprivate, max-age=600
no-cacheNe pas utiliser sans validation (304 requis)no-cache
no-storeInterdire complètement la mise en cacheno-store
must-revalidateAprès max-age, doit revalider auprès de l’originemax-age=3600, must-revalidate
immutableLa ressource ne changera pas (pour les ressources statiques versionnées)max-age=31536000, immutable

max-age est la directive la plus importante. Elle interdit au client d’effectuer une requête au serveur pendant la durée spécifiée. Pour les ressources statiques (CSS, JS, images), max-age est généralement défini de 1 jour à 1 an. Pour les réponses API — de 0 seconde (données toujours fraîches) à 5-10 minutes (données de référence). s-maxage permet de définir différentes durées de vie pour le CDN et le navigateur : le CDN stocke une copie pendant 1 jour, le navigateur pendant 1 heure.

no-cache vs no-store

Ces deux directives sont souvent confondues. no-cache n’interdit pas la mise en cache — il exige de valider la copie mise en cache à chaque utilisation via une requête conditionnelle (If-Modified-Since ou If-None-Match). Si le serveur répond avec 304 — le client utilise le cache. Si 200 — il le met à jour. no-store, quant à lui, interdit complètement de sauvegarder la réponse dans un cache, y compris sur le disque et en mémoire. Utilisez no-store uniquement pour les données sensibles — jetons, données de paiement, documents personnels.

Cache-Control vs Expires

L’en-tête Expires (HTTP/1.0) spécifie également la durée de vie de la ressource mais utilise une date absolue : Expires: Thu, 03 Jul 2026 12:00:00 GMT. Cache-Control max-age utilise le temps relatif à partir du moment de la réponse. La différence est cruciale pour les systèmes distribués : si le serveur et le client sont dans des fuseaux horaires différents, Expires peut être mal interprété. Cache-Control n’a pas ce problème — 3600 secondes sont toujours 3600 secondes.

Lorsque les deux en-têtes sont présents, Cache-Control a priorité sur Expires. Ceci est défini dans RFC 7234 : « Si une réponse inclut un champ Cache-Control avec la directive max-age, le destinataire DOIT ignorer le champ Expires. » En pratique, il est recommandé de ne pas renvoyer Expires pour les clients modernes, car Cache-Control couvre tous les scénarios d’Expires. Cependant, pour la compatibilité ascendante avec les anciens proxy et navigateurs, les deux en-têtes peuvent être renvoyés.

Expires a survécu principalement pour le contenu statique sur Nginx et Apache — ces serveurs ajoutent automatiquement les deux en-têtes. Si votre projet rencontre Expires sans Cache-Control, remplacez-le par Cache-Control avec max-age : la précision du contrôle du cache s’améliore et la dépendance au fuseau horaire est éliminée. Pour la migration, il suffit de configurer le serveur pour ajouter Cache-Control au lieu d’Expires.

nginx
# Nginx : Cache-Control pour les fichiers statiques
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 30d;
    add_header Cache-Control "public, immutable, max-age=2592000";
}

# Différentes politiques pour différents types de contenu
location /api/config {
    expires -1;
    add_header Cache-Control "no-cache, must-revalidate";
}

location /api/static-data {
    expires 5m;
    add_header Cache-Control "public, max-age=300";
}

Dans la configuration Nginx, les fichiers statiques (CSS, JS, images) sont définis avec Cache-Control pendant 30 jours avec l’attribut immutable — cet attribut indique au navigateur que la ressource ne change jamais à cette URL (versionnage via hash dans le nom du fichier). Les points de terminaison API utilisent no-cache pour les données dynamiques et public avec un max-age court pour les données de référence — listes fréquemment demandées et rarement modifiées.

Mise en cache dans les applications mobiles

Dans les applications mobiles, Cache-Control joue un rôle particulier en raison des limites des réseaux mobiles : latence élevée, connexion instable, limites de trafic. Une mise en cache appropriée permet d’afficher les données à l’utilisateur instantanément, même hors ligne, et de les mettre à jour en arrière-plan. OkHttp sur Android et URLSession sur iOS disposent de systèmes de cache intégrés qui respectent Cache-Control.

OkHttp utilise CacheInterceptor, qui lit Cache-Control à partir de la réponse et gère automatiquement la mise en cache. Si le serveur a renvoyé Cache-Control: max-age=3600, OkHttp n’effectuera pas de requête au serveur pendant une heure. Après l’expiration de max-age, OkHttp envoie une requête conditionnelle avec If-Modified-Since et If-None-Match. Configuration du cache dans OkHttp : OkHttpClient.Builder().cache(Cache(directory, maxSize)).

kotlin
fun createCachedClient(cacheDir: File): OkHttpClient {
    return OkHttpClient.Builder()
        .cache(Cache(cacheDir, 10L * 1024 * 1024))
        .addNetworkInterceptor { chain ->
            val response = chain.proceed(chain.request())
            response.newBuilder()
                .header("Cache-Control",
                    "public, max-age=300")
                .removeHeader("Pragma")
                .build()
        }
        .build()
}

Le code crée un OkHttpClient avec un cache de 10 Mo et remplace Cache-Control via NetworkInterceptor. Si le serveur ne renvoie pas Cache-Control ou utilise Expires, l’intercepteur ajoute public, max-age=300 (5 minutes). L’intercepteur supprime l’en-tête obsolète Pragma (HTTP/1.0) pour la compatibilité. La mise en cache sur iOS fonctionne de manière similaire via URLCache.shared avec les paramètres memoryCapacity et diskCapacity.

Mode hors ligne et stale-while-revalidate

La directive stale-while-revalidate permet d’afficher à l’utilisateur un cache obsolète pendant que l’application récupère de nouvelles données en arrière-plan. Cela procure un effet de réponse instantanée : l’utilisateur voit le contenu immédiatement et, après une seconde, il est mis à jour vers la version actuelle. Pris en charge par OkHttp à partir de la version 3.10 et URLCache sur iOS 14+. Exemple : Cache-Control: max-age=3600, stale-while-revalidate=300 — 1 heure de cache actualisé, puis 5 minutes d’affichage de données obsolètes avec actualisation en arrière-plan.

Exemples de configuration de Cache-Control

Différents types de ressources nécessitent différentes stratégies de mise en cache. Examinons les configurations optimales pour les scénarios typiques du développement mobile. Pour le contenu statique avec un hash dans le nom du fichier (bundle.abc123.js), vous pouvez définir max-age jusqu’à 1 an avec immutable. Pour les listes API rarement mises à jour (annuaires, catégories) — max-age de 5 minutes à 1 heure avec stale-while-revalidate.

Type de ressourceCache-ControlExplication
Ressources statiques versionnéespublic, max-age=31536000, immutable1 an, les fichiers ne changent pas (hash dans l’URL)
Ressources statiques non versionnéespublic, max-age=86400, must-revalidate1 jour avec revalidation forcée après
API : données de référencepublic, max-age=600, stale-while-revalidate=6010 minutes de cache + 1 minute obsolète
API : données utilisateurprivate, max-age=601 minute, uniquement pour un utilisateur spécifique
API : données sensiblesno-storeInterdiction complète de mise en cache
Pages HTMLno-cache, must-revalidateValidation à chaque requête, 304 si inchangé

Il est important de se souvenir de la sécurité : pour les réponses contenant des données personnelles de l’utilisateur, définissez toujours private. Sans cette directive, un proxy public (par exemple, d’entreprise) peut mettre en cache la réponse et la fournir à un autre utilisateur. Pour les jetons d’authentification et les informations de paiement, utilisez no-store — même un cache privé ne doit pas stocker ces données sur le disque.

Débogage du cache

Pour vérifier l’exactitude de Cache-Control, utilisez l’en-tête Age (combien de secondes le cache a été stocké) et X-Cache (hit/miss sur le CDN). Dans le navigateur — l’onglet Réseau, la colonne Taille affiche « from disk cache » ou « 304 Not Modified ». Si une ressource devrait être mise en cache mais se charge à chaque fois, vérifiez si le serveur ajoute Cache-Control: no-cache ou Pragma: no-cache avec vos directives.

Foire aux questions

Quelle est la différence entre max-age et s-maxage ?

max-age s’applique à tous les caches (y compris les navigateurs), s-maxage s’applique uniquement aux caches partagés (proxy, CDN). Si s-maxage est spécifié, le CDN ignore max-age et utilise s-maxage. Cela permet de définir des durées de vie différentes pour le navigateur et le CDN.

Peut-on annuler la mise en cache après avoir envoyé Cache-Control ?

Non, après avoir envoyé une réponse avec max-age, le client n’effectuera pas de requête jusqu’à l’expiration du minuteur. Pour une invalidation immédiate du cache, vous devez modifier l’URL de la ressource (ajouter une version/hash) et envoyer des notifications push ou des messages WebSocket pour une réinitialisation forcée.

Qu’est-ce que la directive immutable ?

La directive immutable (RFC 8246) indique au navigateur que la ressource ne changera jamais à cette URL. Le navigateur n’essaie même pas d’effectuer une requête conditionnelle lors de l’actualisation de la page — il utilise le cache jusqu’à l’expiration de max-age. Fonctionne uniquement avec les fichiers versionnés.

Comment Cache-Control affecte-t-il le SEO ?

Googlebot prend en compte Cache-Control : une mise en cache longue accélère le crawling répété. noindex avec un cache rapide est acceptable. no-store peut ralentir l’indexation car Googlebot chargera la page à partir de zéro à chaque fois. Un max-age trop court augmente la charge du serveur lors du crawling.

Comment configurer Cache-Control dans Express.js ?

Via helmet ou un middleware : res.set('Cache-Control', 'public, max-age=3600'). Pour les fichiers statiques, utilisez express.static avec le paramètre maxAge : express.static('public', {maxAge: '1y'}). Pour les routes dynamiques — individuellement dans chaque gestionnaire.

Résumé

  • Cache-Control — le principal en-tête HTTP pour la gestion du cache avec un système flexible de directives
  • max-age — durée de vie en secondes à partir de la réponse ; directive clé pour tous les scénarios de cache
  • private vs public — private uniquement pour le client, public pour les proxy et CDN ; affecte la sécurité des données
  • no-cache exige une validation, no-store interdit complètement le cache ; objectifs différents, ne pas confondre
  • s-maxage — remplace max-age pour les caches partagés, utile pour diviser les politiques navigateur/CDN
  • stale-while-revalidate — affichage du cache obsolète avec actualisation en arrière-plan pour une UX instantanée
  • Recommandation — configurez Cache-Control pour chaque type de ressource sur le serveur et dans le client HTTP mobile

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi