HTTP-Cache: Strong-Cache, Verhandlungscache und CDN-Strategien
HTTP-Cache: Die erste Verteidigungslinie der Performance-Optimierung
Eine richtige Cache-Konfiguration ermöglicht null Netzwerkanfragen beim zweiten Zugriff und reduziert die Ladezeit von Sekunden auf Millisekunden.
| Cache-Typ | Mechanismus | Serveranfrage? | Geschwindigkeit |
|---|---|---|---|
| Stark-Cache | Cache-Control / Expires | Nein | Am schnellsten (0ms) |
| Verhandlungscache | ETag / Last-Modified | Ja (Bedingte Anfrage) | Schnell (304-Antwort) |
| Kein Cache | no-cache / no-store | Ja (Vollständige Anfrage) | Am langsamsten |
I. Stark-Cache
Cache-Control-Direktiven
Cache-Control: max-age=31536000, immutable
| Direktive | Funktion | Anwendungsfall |
|---|---|---|
max-age=N |
N Sekunden cachen | Statische Ressourcen |
s-maxage=N |
CDN N Sekunden cachen (überschreibt max-age) | CDN-Szenarien |
immutable |
Nicht neu validieren, auch wenn abgelaufen | Dateinamen mit Hash |
public |
Zwischencache erlauben | CDN |
private |
Nur Browser-Cache | Personalisierte Inhalte |
no-cache |
Vor jeder Nutzung validieren | HTML-Seiten |
no-store |
Gar nicht cachen | Sensible Daten |
must-revalidate |
Nach Ablauf validieren | API-Antworten |
stale-while-revalidate=N |
Nach Ablauf alten Wert zurückgeben, im Hintergrund aktualisieren | Progressive Aktualisierung |
Expires (Alter Standard)
Expires: Thu, 02 Jun 2027 00:00:00 GMT
Priorität: Cache-Control: max-age > Expires.
II. Verhandlungscache
ETag / If-None-Match
# Erste Anfrage
GET /api/data
→ 200 OK
ETag: "abc123"
Cache-Control: max-age=0
# Nächste Anfrage (bedingt)
GET /api/data
If-None-Match: "abc123"
→ 304 Not Modified (Kein Antwortkörper, spart Bandbreite)
Last-Modified / If-Modified-Since
# Erste Anfrage
GET /style.css
→ 200 OK
Last-Modified: Mon, 01 Jun 2026 12:00:00 GMT
# Nächste Anfrage
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äzision | Byte-Ebene | Sekunden-Ebene |
| Leistung | Hash-Berechnung nötig | Dateizeit direkt lesen |
| Zuverlässigkeit | Hoch | Niedrig (mehrere Änderungen in 1 Sekunde gehen verloren) |
| Verteilt | Hash-Konsistenz sicherstellen | Natürlich konsistent |
Empfehlung: ETag priorisieren.
III. Cache-Strategie-Matrix
HTML-Seiten
Cache-Control: no-cache
HTML ist die Einstiegsdatei, muss jedes Mal validiert werden, um sicherzustellen, dass Benutzer die neueste Version erhalten.
Statische Ressourcen mit Hash
Cache-Control: max-age=31536000, immutable
Der Dateiname enthält einen Hash (z.B. app.abc123.js), bei Inhaltsänderung ändert sich der Hash → URL ändert sich → neue Anfrage. Die alte URL ändert sich nie, kann ein Jahr gecacht und als immutable markiert werden.
Statische Ressourcen ohne Hash
Cache-Control: max-age=86400, stale-while-revalidate=604800
Nach Ablauf zuerst den alten Wert zurückgeben, im Hintergrund still aktualisieren, für den Benutzer unmerklich.
API-Antworten
Cache-Control: private, max-age=0, must-revalidate
API-Antworten enthalten meist Benutzerdaten, private verbietet CDN-Caching, must-revalidate stellt sicher, dass nach Ablauf keine alten Werte zurückgegeben werden.
IV. Vary-Header: Erweiterung des Cache-Schlüssels
Vary: Accept-Encoding, Accept-Language
Vary teilt dem Cache mit: Neben der URL auch nach den Werten dieser Anfrage-Header zwischen Cache-Versionen unterscheiden.
| Vary-Wert | Bedeutung | Szenario |
|---|---|---|
Accept-Encoding |
Nach Komprimierungsmethode cachen | gzip vs br |
Accept-Language |
Nach Sprache cachen | Mehrsprachige Seiten |
Cookie |
Nach Cookie cachen | Personalisierte Seiten |
* |
Jede Anfrage separat cachen | Entspricht keinem Cache |
Hinweis: Vary: Cookie führt zu sehr niedriger Cache-Trefferrate, mit Vorsicht verwenden.
V. CDN-Cache-Strategie
Origin-Pull-Steuerung
# CDN 1 Tag cachen, Browser 5 Minuten
Cache-Control: public, s-maxage=86400, max-age=300
| Szenario | s-maxage | max-age | Beschreibung |
|---|---|---|---|
| Statische Ressourcen | 31536000 | 31536000 | CDN und Browser lang cachen |
| API-Antworten | 300 | 0 | CDN 5 Minuten cachen, Browser nicht |
| HTML | 60 | 0 | CDN 1 Minute cachen, Browser nicht |
| Personalisierte Inhalte | — | 0 | CDN nicht cachen, Browser nicht |
CDN-Cache-Aktualisierung
| Methode | Geschwindigkeit | Anwendbar |
|---|---|---|
| URL-Vorwärmung | Schnell | Neuer Content live |
| Vollständige Aktualisierung | Langsam | Dringende Korrektur |
| Verzeichnis-Aktualisierung | Mittel | Batch-Update |
| Cache-Control: no-cache | Automatisch | API-Szenarien |
Stale-While-Revalidate in der Praxis
Cache-Control: max-age=60, stale-while-revalidate=86400
Sekunde 0: Anfrage → Cache MISS → Origin-Pull → Frischen Wert zurückgeben
Sekunde 30: Anfrage → Cache HIT → Cache-Wert zurückgeben
Sekunde 90: Anfrage → Cache STALE → Alten Wert sofort zurückgeben + Origin-Pull im Hintergrund
Sekunde 91: Origin-Pull abgeschlossen → Cache aktualisiert
Sekunde 120: Anfrage → Cache HIT → Neuen Wert zurückgeben
Effekt: Der Benutzer wartet nie auf Origin-Pull, stille Aktualisierung im Hintergrund.
VI. Cache-Invalidierungsstrategie
Inhalts-Hash (empfohlen)
<!-- Hash zur Build-Zeit generiert -->
<script src="/app.abc123.js"></script>
<link href="/style.def456.css">
// webpack-Konfiguration
output: {
filename: '[name].[contenthash:8].js',
}
Versionsabfrage-Parameter
<!-- Einfach, aber CDN cached ?v= Parameter möglicherweise nicht -->
<script src="/app.js?v=2.0.0"></script>
Problem: Einige CDNs ignorieren Abfrageparameter, wodurch der Cache nicht aktualisiert wird.
Zeitstempel (nicht empfohlen)
<!-- Ändert sich jedes Mal, zerstört den Cache vollständig -->
<script src="/app.js?t=1717315200"></script>
VII. Service-Worker-Cache
Cache-First-Strategie
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request)
.then(cached => cached || fetch(event.request))
);
});
Stale-While-Revalidate-Strategie
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;
})
)
);
});
Cache-Strategie-Auswahl
| Strategie | Prioritätsquelle | Anwendbar |
|---|---|---|
| Cache First | Cache | Schriften, Bilder |
| Network First | Netzwerk | API, HTML |
| Stale While Revalidate | Cache + Hintergrundaktualisierung | CSS, JS |
| Network Only | Netzwerk | Nicht-GET-Anfragen |
| Cache Only | Cache | Offline-Seiten |
VIII. Cache-Debugging
Chrome DevTools
- DevTools → Network-Panel
- Spalte
Sizeprüfen:from disk cache: Disk-Cache-Trefferfrom memory cache: Speicher-Cache-Treffer- Tatsächliche Größe: Kein Treffer
Age-Antwort-Header prüfen: Wie lange bereits gecacht- Disable cache aktivieren: Cache deaktivieren (wenn DevTools offen)
Curl-Verifikation
# Antwort-Header anzeigen
curl -I https://example.com/style.css
# Bedingte Anfrage senden
curl -I -H 'If-None-Match: "abc123"' https://example.com/style.css
# 304 bedeutet Verhandlungscache-Treffer
# Anderes Accept-Encoding simulieren
curl -I -H 'Accept-Encoding: br' https://example.com/style.css
IX. Best-Practices-Checkliste
- HTML: no-cache, Einstiegsdatei immer aktuell halten
- JS/CSS mit Hash: max-age=1 Jahr + immutable
- API: must-revalidate, nach Ablauf validieren
- CDN: s-maxage zur Steuerung der Origin-Pull-Frequenz
- Vary: Accept-Encoding, Komprimierungsmethoden unterscheiden
- ETag verwenden statt Last-Modified
- stale-while-revalidate für unmerkliche Aktualisierung
- Service Worker für Offline-Fähigkeiten ergänzen