Aller au contenu principal

[Medium] 📄 HTTP Caching

1. What is HTTP caching and why is it important?​

Qu'est-ce que le cache HTTP ? Pourquoi est-il important ?

Le cache HTTP est une technique qui stocke temporairement les rĂ©ponses HTTP cĂŽtĂ© client (navigateur) ou sur des serveurs intermĂ©diaires, afin de pouvoir utiliser directement les donnĂ©es mises en cache lors des requĂȘtes suivantes, sans avoir Ă  les redemander au serveur.

Cache vs stockage temporaire : quelle est la diffĂ©rence ?​

Dans la documentation technique, ces deux termes sont souvent utilisés de maniÚre interchangeable, mais ils ont en réalité des significations différentes :

Cache​

Définition : Copies de données stockées pour l'optimisation des performances, mettant l'accent sur la "réutilisation" et l'"accÚs plus rapide".

Caractéristiques :

  • ✅ L'objectif est d'amĂ©liorer les performances
  • ✅ Les donnĂ©es peuvent ĂȘtre rĂ©utilisĂ©es
  • ✅ Politiques d'expiration clairement dĂ©finies
  • ✅ GĂ©nĂ©ralement des copies des donnĂ©es originales

Exemple :

// HTTP Cache - Mettre en cache les réponses d'API
Cache-Control: max-age=3600 // Cache pendant 1 heure

// Memory Cache - Mettre en cache les résultats de calcul
const cache = new Map();
function fibonacci(n) {
if (cache.has(n)) return cache.get(n); // Réutiliser le cache
const result = /* calcul */;
cache.set(n, result);
return result;
}

Temporary Storage (Stockage temporaire)​

Définition : Données stockées temporairement, mettant l'accent sur la "temporalité" et "seront supprimées".

Caractéristiques :

  • ✅ L'objectif est le stockage temporaire
  • ✅ Pas nĂ©cessairement rĂ©utilisĂ©
  • ✅ Cycle de vie gĂ©nĂ©ralement court
  • ✅ Peut contenir des Ă©tats intermĂ©diaires

Exemple :

// sessionStorage - Stocker temporairement les entrées utilisateur
sessionStorage.setItem('formData', JSON.stringify(form)); // Supprimé à la fermeture de l'onglet

// Stockage temporaire des fichiers téléchargés
const tempFile = await uploadToTemp(file); // Supprimer aprĂšs traitement
await processFile(tempFile);
await deleteTempFile(tempFile);

Tableau comparatif​

CaractéristiqueCacheTemporary Storage (Stockage temporaire)
Objectif principalOptimisation des performancesStockage temporaire
RéutilisationOui, lectures multiplesPas nécessairement
Cycle de vieBasé sur la politiqueGénéralement court
Usage typiqueHTTP Cache, Memory CachesessionStorage, fichiers temporaires
Équivalent anglaisCacheTemp / Temporary / Buffer

DiffĂ©rences dans l'application pratique​

// ===== Scénarios d'utilisation du Cache =====

// 1. HTTP Cache : Réutiliser les réponses d'API
fetch('/api/users') // PremiĂšre requĂȘte
.then((response) => response.json());

fetch('/api/users') // DeuxiĂšme lecture depuis le cache
.then((response) => response.json());

// 2. Cache des résultats de calcul
const memoize = (fn) => {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key); // Réutiliser
const result = fn(...args);
cache.set(key, result);
return result;
};
};

// ===== Scénarios d'utilisation du Stockage temporaire =====

// 1. Stockage temporaire des données de formulaire (prévenir la fermeture accidentelle)
window.addEventListener('beforeunload', () => {
sessionStorage.setItem('formDraft', JSON.stringify(formData));
});

// 2. Stockage temporaire des fichiers téléchargés
async function handleUpload(file) {
const tempPath = await uploadToTempStorage(file); // Stockage temporaire
const processed = await processFile(tempPath);
await deleteTempFile(tempPath); // Supprimer aprĂšs utilisation
return processed;
}

// 3. Stockage temporaire des résultats intermédiaires
const tempResults = []; // Stocker les résultats intermédiaires
for (const item of items) {
tempResults.push(process(item));
}
const final = combine(tempResults); // Plus nécessaire aprÚs utilisation

Application dans le dĂ©veloppement web​

// HTTP Cache - Stockage à long terme, réutilisation
Cache-Control: public, max-age=31536000, immutable
// → Le navigateur mettra ce fichier en cache pendant un an et le rĂ©utilisera

// sessionStorage (Stockage temporaire) - Stockage temporaire, supprimé à la fermeture
sessionStorage.setItem('tempData', data);
// → Valide uniquement dans l'onglet actuel, supprimĂ© Ă  la fermeture

// localStorage (Stockage Ă  long terme) - Entre les deux
localStorage.setItem('userPreferences', prefs);
// → Stockage persistant, mais pas pour l'optimisation des performances

Pourquoi est-il important de distinguer ces deux concepts ?​

  1. Décisions de conception :

    • Besoin d'optimisation des performances ? → Utiliser le cache
    • Besoin de stockage temporaire ? → Utiliser le stockage temporaire
  2. Gestion des ressources :

    • Cache : Focus sur le taux de rĂ©ussite et les politiques d'expiration
    • Stockage temporaire : Focus sur le moment du nettoyage et les limites de capacitĂ©
  3. Réponses en entretien :

    • "Comment optimiser les performances" → Parler des stratĂ©gies de cache
    • "Comment gĂ©rer les donnĂ©es temporaires" → Parler des solutions de stockage temporaire

Dans cet article, nous discutons principalement du Cache, en particulier du mécanisme de cache HTTP.

Avantages du cache​

  1. RĂ©duction des requĂȘtes rĂ©seau : Lire directement depuis le cache local, sans envoyer de requĂȘtes HTTP
  2. RĂ©duction de la charge serveur : Moins de requĂȘtes Ă  traiter par le serveur
  3. Vitesse de chargement des pages plus rapide : La lecture du cache local est beaucoup plus rapide que les requĂȘtes rĂ©seau
  4. Économie de bande passante : RĂ©duction du volume de transfert de donnĂ©es
  5. Amélioration de l'expérience utilisateur : Réponses de page plus rapides, utilisation plus fluide

Types de cache​

┌─────────────────────────────────────┐
│ HiĂ©rarchie du cache navigateur │
├──────────────────────────────────────
│ 1. Memory Cache (Cache mĂ©moire) │
│ - Le plus rapide, petite │
│ capacitĂ© │
│ - SupprimĂ© Ă  la fermeture │
│ de l'onglet │
├──────────────────────────────────────
│ 2. Disk Cache (Cache disque) │
│ - Plus lent, grande capacitĂ© │
│ - Stockage persistant │
├──────────────────────────────────────
│ 3. Service Worker Cache │
│ - Contrîle total du │
│ dĂ©veloppeur │
│ - Support des applications │
│ hors ligne │
└─────────────────────────────────────┘

2. What are the HTTP caching strategies?​

Quelles sont les stratégies de cache HTTP ?

Classification des stratĂ©gies de cache​

Stratégies de cache HTTP
├── Cache fort (Strong Cache)
│ ├── Cache-Control
│ └── Expires
└── Cache de nĂ©gociation (Negotiation Cache)
├── Last-Modified / If-Modified-Since
└── ETag / If-None-Match

1. Cache fort (Strong Cache / Fresh)​

CaractĂ©ristique : Le navigateur lit directement depuis le cache local sans envoyer de requĂȘte au serveur.

Cache-Control (HTTP/1.1)​

Cache-Control: max-age=3600

Directives courantes :

// 1. max-age : Durée de validité du cache (secondes)
Cache-Control: max-age=3600 // Cache pendant 1 heure

// 2. no-cache : Validation auprÚs du serveur requise (cache de négociation)
Cache-Control: no-cache

// 3. no-store : Ne pas mettre en cache du tout
Cache-Control: no-store

// 4. public : Peut ĂȘtre mis en cache par n'importe quel cache (navigateur, CDN)
Cache-Control: public, max-age=31536000

// 5. private : Seul le navigateur peut mettre en cache
Cache-Control: private, max-age=3600

// 6. immutable : La ressource ne change jamais (avec nom de fichier hash)
Cache-Control: public, max-age=31536000, immutable

// 7. must-revalidate : AprĂšs expiration, validation auprĂšs du serveur obligatoire
Cache-Control: max-age=3600, must-revalidate

Expires (HTTP/1.0, obsolùte)​

Expires: Wed, 21 Oct 2025 07:28:00 GMT

ProblĂšmes :

  • Utilise un temps absolu, dĂ©pend de l'heure du client
  • Une heure client inexacte entraĂźne un dysfonctionnement du cache
  • RemplacĂ© par Cache-Control

2. Cache de nĂ©gociation (Negotiation Cache / Validation)​

CaractĂ©ristique : Le navigateur envoie une requĂȘte au serveur pour vĂ©rifier si la ressource a Ă©tĂ© mise Ă  jour.

Last-Modified / If-Modified-Since​

# RĂ©ponse du serveur (premiĂšre requĂȘte)
Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT

# RequĂȘte du navigateur (requĂȘtes suivantes)
If-Modified-Since: Wed, 21 Oct 2024 07:28:00 GMT

Processus :

  1. PremiĂšre requĂȘte : Le serveur renvoie Last-Modified
  2. RequĂȘtes suivantes : Le navigateur inclut If-Modified-Since
  3. Ressource non modifiée : Le serveur renvoie 304 Not Modified
  4. Ressource modifiée : Le serveur renvoie 200 OK et la nouvelle ressource

ETag / If-None-Match​

# RĂ©ponse du serveur (premiĂšre requĂȘte)
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

# RequĂȘte du navigateur (requĂȘtes suivantes)
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

Avantages :

  • Plus prĂ©cis que Last-Modified
  • Ne dĂ©pend pas du temps, utilise le hash du contenu
  • Peut dĂ©tecter les changements en dessous de la seconde

Last-Modified vs ETag​

CaractéristiqueLast-ModifiedETag
PrécisionNiveau secondeHash du contenu, plus précis
PerformancePlus rapideCalcul de hash nécessaire, plus lent
Cas d'utilisationRessources statiques généralesRessources nécessitant un contrÎle précis
PrioritéBasseHaute (ETag prioritaire)

3. How does browser caching work?​

Comment fonctionne le cache du navigateur ?

Flux de cache complet​

┌──────────────────────────────────────────────┐
│ Flux de requĂȘte de ressources du │
│ navigateur │
└──────────────────────────────────────────────┘
↓
1. Vérifier Memory Cache
↓
┌───────┮────────┐
│ Cache trouvĂ© ? │
└───────┬────────┘
Yes │ No
↓
2. Vérifier Disk Cache
↓
┌───────┮────────┐
│ Cache trouvĂ© ? │
└───────┬────────┘
Yes │ No
↓
3. Vérifier Service Worker
↓
┌───────┮────────┐
│ Cache trouvĂ© ? │
└───────┬────────┘
Yes │ No
↓
4. Vérifier l'expiration du cache
↓
┌───────┮────────┐
│ ExpirĂ© ? │
└───────┬────────┘
Yes │ No
↓
5. Valider avec le cache de négociation
↓
┌───────┮────────┐
│ Ressource │
│ modifiĂ©e ? │
└───────┬────────┘
Yes │ No (304)
↓
6. Demander une nouvelle ressource au serveur
↓
┌───────┮────────┐
│ Renvoyer │
│ nouvelle │
│ ressource │
│ (200 OK) │
└────────────────┘

Exemple pratique​

// PremiĂšre requĂȘte
GET /api/data.json
Response:
200 OK
Cache-Control: max-age=3600
ETag: "abc123"

{ data: "..." }

// ========== Nouvelle requĂȘte dans l'heure ==========
// Cache fort : Lire directement depuis le local, sans envoyer de requĂȘte
// Status: 200 OK (from disk cache)

// ========== Nouvelle requĂȘte aprĂšs 1 heure ==========
// Cache de nĂ©gociation : Envoyer une requĂȘte de validation
GET /api/data.json
If-None-Match: "abc123"

// Ressource non modifiée
Response:
304 Not Modified
(Pas de body, utiliser le cache local)

// Ressource modifiée
Response:
200 OK
ETag: "def456"

{ data: "new data" }

4. What are the common caching strategies?​

Quelles sont les stratégies de cache les plus courantes ?

1. StratĂ©gie de cache permanent (pour les ressources statiques)​

// HTML : Ne pas mettre en cache, vérifier à chaque fois
Cache-Control: no-cache

// CSS/JS (avec hash) : Cache permanent
Cache-Control: public, max-age=31536000, immutable
// Nom de fichier : main.abc123.js

Principe :

  • Le HTML n'est pas mis en cache, garantissant que l'utilisateur obtient la derniĂšre version
  • CSS/JS utilisent des noms de fichiers avec hash, le nom change quand le contenu change
  • Les anciennes versions ne sont pas utilisĂ©es, les nouvelles sont retĂ©lĂ©chargĂ©es

2. StratĂ©gie pour les ressources frĂ©quemment mises Ă  jour​

// Données d'API : Cache de courte durée + cache de négociation
Cache-Control: max-age=60, must-revalidate
ETag: "abc123"

3. StratĂ©gie pour les ressources d'images​

// Avatar utilisateur : Cache Ă  moyen terme
Cache-Control: public, max-age=86400 // 1 jour

// Logo, icĂŽnes : Cache Ă  long terme
Cache-Control: public, max-age=2592000 // 30 jours

// Images dynamiques : Cache de négociation
Cache-Control: no-cache
ETag: "image-hash"

4. Recommandations de cache par type de ressource​

const cachingStrategies = {
// Fichiers HTML
html: 'Cache-Control: no-cache',

// Ressources statiques avec hash
staticWithHash: 'Cache-Control: public, max-age=31536000, immutable',

// Ressources statiques rarement mises Ă  jour
staticAssets: 'Cache-Control: public, max-age=2592000',

// Données d'API
apiData: 'Cache-Control: private, max-age=60',

// Données spécifiques à l'utilisateur
userData: 'Cache-Control: private, no-cache',

// Données sensibles
sensitive: 'Cache-Control: no-store',
};

5. Service Worker caching​

Cache Service Worker

Le Service Worker offre le contrÎle de cache le plus flexible, permettant aux développeurs de contrÎler entiÚrement la logique de cache.

Utilisation de base​

// Enregistrer le Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}
// sw.js - Fichier Service Worker
const CACHE_NAME = 'my-app-v1';
const urlsToCache = [
'/',
'/styles/main.css',
'/scripts/main.js',
'/images/logo.png',
];

// ÉvĂ©nement d'installation : Mettre en cache les ressources statiques
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(urlsToCache);
})
);
});

// Interception des requĂȘtes : Utiliser la stratĂ©gie de cache
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
// Stratégie Cache First
return response || fetch(event.request);
})
);
});

// ÉvĂ©nement d'activation : Nettoyer l'ancien cache
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (cacheName !== CACHE_NAME) {
return caches.delete(cacheName);
}
})
);
})
);
});

StratĂ©gies de cache courantes​

1. Cache First (Cache en premier)​

// Adapté pour : Ressources statiques
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});

2. Network First (RĂ©seau en premier)​

// AdaptĂ© pour : RequĂȘtes d'API
self.addEventListener('fetch', (event) => {
event.respondWith(
fetch(event.request)
.then((response) => {
// Mettre Ă  jour le cache
const responseClone = response.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(event.request, responseClone);
});
return response;
})
.catch(() => {
// Réseau échoué, utiliser le cache
return caches.match(event.request);
})
);
});

3. Stale While Revalidate (Obsolùte pendant la revalidation)​

// Adapté pour : Ressources nécessitant des réponses rapides tout en restant à jour
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((cachedResponse) => {
const fetchPromise = fetch(event.request).then((networkResponse) => {
caches.open(CACHE_NAME).then((cache) => {
cache.put(event.request, networkResponse.clone());
});
return networkResponse;
});

// Renvoyer le cache, mettre Ă  jour en arriĂšre-plan
return cachedResponse || fetchPromise;
})
);
});

6. How to implement cache busting?​

Comment implémenter le Cache Busting ?

Le Cache Busting est une technique qui garantit que les utilisateurs obtiennent les ressources les plus récentes.

MĂ©thode 1 : Hash dans le nom de fichier (recommandĂ©e)​

// Utiliser des outils de bundling comme Webpack/Vite
// Sortie : main.abc123.js

// webpack.config.js
module.exports = {
output: {
filename: '[name].[contenthash].js',
},
};
<!-- Mettre à jour automatiquement la référence -->
<script src="/js/main.abc123.js"></script>

Avantages :

  • ✅ Le nom de fichier change, forçant le tĂ©lĂ©chargement du nouveau fichier
  • ✅ L'ancienne version reste en cache, pas de gaspillage
  • ✅ Meilleure pratique

MĂ©thode 2 : NumĂ©ro de version dans le Query String​

<!-- Mettre à jour manuellement le numéro de version -->
<script src="/js/main.js?v=1.2.3"></script>
<link rel="stylesheet" href="/css/style.css?v=1.2.3" />

Inconvénients :

  • ❌ Certains CDN ne mettent pas en cache les ressources avec un query string
  • ❌ Maintenance manuelle du numĂ©ro de version nĂ©cessaire

MĂ©thode 3 : Horodatage​

// Utiliser en environnement de développement
const timestamp = Date.now();
const script = document.createElement('script');
script.src = `/js/main.js?t=${timestamp}`;
document.body.appendChild(script);

Usage :

  • Éviter le cache en environnement de dĂ©veloppement
  • InadaptĂ© Ă  l'environnement de production (chaque fois une nouvelle requĂȘte)

7. Common caching interview questions​

Questions d'entretien courantes sur le cache

Question 1 : Comment empĂȘcher le HTML d'ĂȘtre mis en cache ?​

Cliquez pour voir la réponse
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0

Ou utiliser des balises meta :

<meta
http-equiv="Cache-Control"
content="no-cache, no-store, must-revalidate"
/>
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />

Question 2 : Pourquoi utiliser ETag plutît que seulement Last-Modified ?​

Cliquez pour voir la réponse

Avantages de l'ETag :

  1. Plus précis : Peut détecter les changements en dessous de la seconde
  2. Basé sur le contenu : Basé sur le hash du contenu, pas sur le temps
  3. Éviter les problùmes de temps :
    • Le contenu du fichier n'a pas changĂ© mais l'heure a changĂ© (comme lors d'un redĂ©ploiement)
    • Ressources mises Ă  jour cycliquement (retour pĂ©riodique au mĂȘme contenu)
  4. SystĂšmes distribuĂ©s : Les horloges de diffĂ©rents serveurs peuvent ne pas ĂȘtre synchronisĂ©es

Exemple :

// Le contenu du fichier n'a pas changé, mais Last-Modified a changé
// 2024-01-01 12:00 - Déployer version A (contenu : abc)
// 2024-01-02 12:00 - Redéployer version A (contenu : abc)
// Last-Modified a changĂ©, mais le contenu est le mĂȘme !

// ETag n'a pas ce problĂšme
ETag: 'hash-of-abc'; // Toujours identique

Question 3 : Quelle est la diffĂ©rence entre from disk cache et from memory cache ?​

Cliquez pour voir la réponse
CaractéristiqueMemory CacheDisk Cache
EmplacementMémoire (RAM)Disque dur
VitesseExtrĂȘmement rapidePlus lent
CapacitéPetite (niveau Mo)Grande (niveau Go)
PersistanceSupprimé à la fermeture de l'ongletStockage persistant
PrioritéHaute (prioritaire)Basse

Ordre de priorité de chargement :

1. Memory Cache (le plus rapide)
2. Service Worker Cache
3. Disk Cache
4. HTTP Cache
5. RequĂȘte rĂ©seau (le plus lent)

Conditions de déclenchement :

  • Memory Cache : Ressources rĂ©cemment accĂ©dĂ©es (comme le rechargement de la page)
  • Disk Cache : Ressources accĂ©dĂ©es il y a longtemps ou fichiers volumineux

Question 4 : Comment forcer le navigateur à recharger les ressources ?​

Cliquez pour voir la réponse

Phase de développement :

// 1. Hard Reload (Ctrl/Cmd + Shift + R)
// 2. Vider le cache et recharger

// 3. Ajouter un horodatage dans le code
const script = document.createElement('script');
script.src = `/js/main.js?t=${Date.now()}`;

Environnement de production :

// 1. Utiliser le hash dans le nom de fichier (meilleure pratique)
main.abc123.js // Généré automatiquement par Webpack/Vite

// 2. Mettre à jour le numéro de version
<script src="/js/main.js?v=2.0.0"></script>

// 3. Configurer Cache-Control
Cache-Control: no-cache // Forcer la validation
Cache-Control: no-store // Ne pas mettre en cache du tout

Question 5 : Comment implĂ©menter le cache hors ligne PWA ?​

Cliquez pour voir la réponse
// sw.js - Service Worker
const CACHE_NAME = 'pwa-v1';
const OFFLINE_URL = '/offline.html';

// Mettre en cache la page hors ligne lors de l'installation
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll([
OFFLINE_URL,
'/styles/offline.css',
'/images/offline-icon.png',
]);
})
);
});

// Interception des requĂȘtes
self.addEventListener('fetch', (event) => {
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request).catch(() => {
// Réseau échoué, afficher la page hors ligne
return caches.match(OFFLINE_URL);
})
);
}
});

Stratégie de cache PWA complÚte :

// 1. Mettre en cache les ressources statiques
caches.addAll(['/css/', '/js/', '/images/']);

// 2. RequĂȘtes d'API : Network First
// 3. Images : Cache First
// 4. HTML : Network First, afficher la page hors ligne en cas d'échec

8. Best practices​

Bonnes pratiques

✅ Pratiques recommandĂ©es​

// 1. HTML - Ne pas mettre en cache, garantir que l'utilisateur obtient la derniĂšre version
// Response Headers:
Cache-Control: no-cache

// 2. CSS/JS (avec hash) - Cache permanent
// Nom de fichier : main.abc123.js
Cache-Control: public, max-age=31536000, immutable

// 3. Images - Cache Ă  long terme
Cache-Control: public, max-age=2592000 // 30 jours

// 4. Données d'API - Cache à court terme + cache de négociation
Cache-Control: private, max-age=60
ETag: "api-response-hash"

// 5. Utiliser le Service Worker pour le support hors ligne

❌ Pratiques Ă  Ă©viter​

// ❌ Mauvais : Configurer un cache à long terme pour le HTML
Cache-Control: max-age=31536000 // L'utilisateur pourrait voir une ancienne version

// ❌ Mauvais : Utiliser Expires au lieu de Cache-Control
Expires: Wed, 21 Oct 2025 07:28:00 GMT // HTTP/1.0, obsolĂšte

// ❌ Mauvais : Ne configurer aucun cache
// Sans en-tĂȘtes de cache, le comportement du navigateur est indĂ©terminĂ©

// ❌ Mauvais : Utiliser la mĂȘme stratĂ©gie pour toutes les ressources
Cache-Control: max-age=3600 // Devrait ĂȘtre ajustĂ© selon le type de ressource

Arbre de dĂ©cision de la stratĂ©gie de cache​

Ressource statique ?
├─ Oui → Le nom de fichier a un hash ?
│ ├─ Oui → Cache permanent (max-age=31536000, immutable)
│ └─ Non → Cache à moyen-long terme (max-age=2592000)
└─ Non → Est-ce du HTML ?
├─ Oui → Ne pas mettre en cache (no-cache)
└─ Non → Est-ce une API ?
├─ Oui → Cache Ă  court terme + nĂ©gociation (max-age=60, ETag)
└─ Non → DĂ©cider selon la frĂ©quence de mise Ă  jour

Reference​