Unnötige Netzwerkanfragen mit dem HTTP-Cache vermeiden

Ilya Grigorik
Jens Posnick
Jeff Posnick

Das Abrufen von Ressourcen über das Netzwerk ist langsam und teuer:

  • Große Antworten erfordern viele Roundtrips zwischen dem Browser und dem Server.
  • Ihre Seite wird erst geladen, wenn alle zugehörigen kritischen Ressourcen vollständig heruntergeladen wurden.
  • Wenn eine Person mit einem eingeschränkten mobilen Datentarif auf Ihre Website zugreift, ist jede unnötige Netzwerkanfrage Verschwendung.

Wie können Sie unnötige Netzwerkanfragen vermeiden? Der HTTP-Cache des Browsers ist Ihre erste Verteidigungslinie. Diese Methode ist nicht unbedingt der leistungsstärkste oder flexibelste Ansatz und Sie haben nur eine begrenzte Kontrolle über die Lebensdauer von im Cache gespeicherten Antworten. Sie ist jedoch effektiv, wird in allen Browsern unterstützt und erfordert nicht viel Arbeit.

In diesem Leitfaden werden die Grundlagen für eine effektive HTTP-Caching-Implementierung beschrieben.

Browserkompatibilität

Es gibt eigentlich keine einzelne API, die als HTTP-Cache bezeichnet wird. Es ist der allgemeine Name für eine Sammlung von Webplattform-APIs. Diese APIs werden von allen Browsern unterstützt:

Funktionsweise des HTTP-Cache

Alle HTTP-Anfragen des Browsers werden zuerst an den Browser-Cache weitergeleitet, um zu prüfen, ob eine gültige im Cache gespeicherte Antwort vorhanden ist, die zur Verarbeitung der Anfrage verwendet werden kann. Bei einer Übereinstimmung wird die Antwort aus dem Cache gelesen, wodurch sowohl die Netzwerklatenz als auch die durch die Übertragung entstehenden Datenkosten eliminiert werden.

Das Verhalten des HTTP-Cache wird durch eine Kombination aus Anfrageheadern und Antwortheadern gesteuert. Im Idealfall haben Sie sowohl die Kontrolle über den Code für Ihre Webanwendung (der die Anfrageheader bestimmt) als auch die Konfiguration Ihres Webservers (die Antwortheader bestimmt).

Eine ausführlichere konzeptionelle Übersicht findest du im MDN-Artikel HTTP-Caching.

Anfrageheader: Halten Sie sich an die Standardeinstellungen (normalerweise)

Es gibt eine Reihe wichtiger Header, die in die ausgehenden Anfragen Ihrer Webanwendung aufgenommen werden sollten. Der Browser legt sie jedoch fast immer für Sie fest, wenn er Anfragen sendet. Anfrageheader, die die Aktualitätsprüfung beeinflussen, wie If-None-Match und If-Modified-Since, werden nur angezeigt, wenn der Browser die aktuellen Werte im HTTP-Cache versteht.

Das ist eine gute Nachricht: Du kannst weiterhin Tags wie <img src="my-image.png"> in deinen HTML-Code einfügen und der Browser übernimmt das HTTP-Caching automatisch und ohne zusätzlichen Aufwand.

Antwortheader: Webserver konfigurieren

Der wichtigste Teil der HTTP-Caching-Einrichtung sind die Header, die Ihr Webserver jeder ausgehenden Antwort hinzufügt. Die folgenden Header spielen bei dem effektiven Caching-Verhalten eine Rolle:

  • Cache-Control: Der Server kann eine Cache-Control-Anweisung zurückgeben, um festzulegen, wie und wie lange der Browser und andere Zwischen-Caches die einzelne Antwort im Cache speichern sollen.
  • ETag: Wenn der Browser eine abgelaufene im Cache gespeicherte Antwort findet, kann er ein kleines Token (in der Regel ein Hash des Dateiinhalts) an den Server senden, um zu prüfen, ob die Datei geändert wurde. Wenn der Server dasselbe Token zurückgibt, ist die Datei identisch und muss nicht noch einmal heruntergeladen werden.
  • Last-Modified: Dieser Header dient demselben Zweck wie ETag, verwendet jedoch eine zeitbasierte Strategie, um zu bestimmen, ob sich eine Ressource geändert hat, und nicht die inhaltsbasierte Strategie von ETag.

Einige Webserver bieten eine integrierte Unterstützung für das standardmäßige Festlegen dieser Header, während andere Header vollständig weglassen, sofern Sie sie nicht explizit konfigurieren. Die genauen Details, wie Header konfiguriert werden, variieren je nach verwendetem Webserver erheblich. Daher sollten Sie in der Dokumentation Ihres Servers nachschlagen, um möglichst genaue Informationen zu erhalten.

Um Ihnen die Suche zu ersparen, finden Sie hier eine Anleitung zum Konfigurieren einiger beliebter Webserver:

Durch Weglassen des Antwortheaders Cache-Control wird das HTTP-Caching nicht deaktiviert. Stattdessen schätzen Browser, welche Art von Caching für einen bestimmten Inhaltstyp am sinnvollsten ist. Möglicherweise möchten Sie mehr Kontrolle haben, als das bietet. Nehmen Sie sich daher die Zeit, Ihre Antwortheader zu konfigurieren.

Welche Antwortheaderwerte sollten Sie verwenden?

Es gibt zwei wichtige Szenarien, die Sie bei der Konfiguration der Antwortheader Ihres Webservers berücksichtigen sollten.

Langlebiges Caching für versionierte URLs

Wie können versionierte URLs Ihre Caching-Strategie unterstützen?
Versionierte URLs sind eine bewährte Methode, da sie die Entwertung von im Cache gespeicherten Antworten erleichtern.

Angenommen, Ihr Server weist Browser an, eine CSS-Datei ein Jahr lang im Cache zu speichern (Cache-Control: max-age=31536000), aber Ihr Designer hat gerade ein Notfallupdate durchgeführt, das Sie sofort bereitstellen müssen. Wie informieren Sie Browser darüber, dass die veraltete, im Cache gespeicherte Kopie der Datei aktualisiert werden muss? Das ist nicht möglich, zumindest nicht, ohne die URL der Ressource zu ändern. Nachdem der Browser die Antwort im Cache gespeichert hat, wird die im Cache gespeicherte Version verwendet, bis sie gemäß max-age oder expires nicht mehr aktuell ist oder aus einem anderen Grund aus dem Cache entfernt wird, z. B. wenn der Nutzer den Browser-Cache leert. Daher können unterschiedliche Nutzer beim Erstellen der Seite unterschiedliche Versionen der Datei verwenden: Nutzer, die die Ressource gerade abgerufen haben, verwenden die neue Version, während Nutzer, die eine frühere (aber noch gültige) Kopie im Cache gespeichert haben, eine ältere Version der Antwort verwenden. Wie können Sie diese beiden Welten optimal nutzen: clientseitiges Caching und schnelle Updates? Sie ändern die URL der Ressource und zwingen den Nutzer, die neue Antwort herunterzuladen, wenn sich ihr Inhalt ändert. Normalerweise betten Sie dazu einen Fingerabdruck der Datei oder eine Versionsnummer in ihren Dateinamen ein, z. B. style.x234dff.css.

Wenn Sie auf Anfragen nach URLs antworten, die „fingerprint“- oder Versionsinformationen enthalten und deren Inhalte sich nie ändern sollen, fügen Sie Cache-Control: max-age=31536000 in Ihre Antworten ein.

Wenn Sie diesen Wert festlegen, weiß der Browser, dass er innerhalb des nächsten Jahres die gleiche URL laden muss (31.536.000 Sekunden, maximal unterstützter Wert), kann er den Wert im HTTP-Cache sofort verwenden, ohne eine Netzwerkanfrage an Ihren Webserver senden zu müssen. Das ist großartig – Sie haben sofort die Zuverlässigkeit und Geschwindigkeit gesteigert, die sich aus der Umgehung des Netzwerks ergeben.

Build-Tools wie Webpack können den Prozess zum Zuweisen von Hash-Fingerabdrücken zu Ihren Asset-URLs automatisieren.

Erneute Servervalidierung für URLs ohne Versionsangabe

Leider sind nicht alle von Ihnen geladenen URLs versioniert. Möglicherweise können Sie vor der Bereitstellung Ihrer Webanwendung keinen Build-Schritt hinzufügen, sodass Sie Ihren Asset-URLs keine Hashes hinzufügen können. Jede Webanwendung benötigt HTML-Dateien. Diese Dateien enthalten (fast!) nie Versionsinformationen, da sich niemand widmet, Ihre Webanwendung zu verwenden, wenn er sich merken muss, dass die zu besuchende URL https://example.com/index.34def12.html lautet. Was können Sie also für diese URLs tun?

Dies ist ein Szenario, in dem Sie sich geschlagen geben müssen. HTTP-Caching allein reicht nicht aus, um das Netzwerk vollständig zu umgehen. (Keine Sorge – Sie erfahren bald mehr über Service Worker, die uns die nötige Unterstützung bieten, um den Kampf zu Ihren Gunsten zurückzuziehen.) Es gibt jedoch einige Schritte, mit denen Sie dafür sorgen können, dass Netzwerkanfragen so schnell und effizient wie möglich verarbeitet werden.

Mit den folgenden Cache-Control-Werten können Sie genauer festlegen, wo und wie nicht versionierte URLs im Cache gespeichert werden:

  • no-cache: Damit wird der Browser angewiesen, jedes Mal eine erneute Überprüfung mit dem Server durchzuführen, bevor eine im Cache gespeicherte Version der URL verwendet werden kann.
  • no-store: Damit werden der Browser und andere Zwischencaches (wie CDNs) angewiesen, niemals eine Version der Datei zu speichern.
  • private. Browser können die Datei im Cache speichern, Zwischen-Caches jedoch nicht.
  • public: Die Antwort kann von einem beliebigen Cache gespeichert werden.

Im Anhang: Cache-Control-Flussdiagramm wird beschrieben, wie Sie entscheiden, welche Cache-Control-Werte verwendet werden sollen. Beachten Sie auch, dass Cache-Control eine durch Kommas getrennte Liste von Anweisungen akzeptieren kann. Siehe Anhang: Cache-Control-Beispiele.

Außerdem kann es hilfreich sein, einen von zwei zusätzlichen Antwortheadern festzulegen: entweder ETag oder Last-Modified. Wie unter Antwortheader erwähnt, dienen ETag und Last-Modified beide demselben Zweck: Es wird ermittelt, ob der Browser eine im Cache gespeicherte Datei, die abgelaufen ist, noch einmal herunterladen muss. ETag ist der empfohlene Ansatz, da er genauer ist.

ETag-Beispiel

Angenommen, seit dem ersten Abruf sind 120 Sekunden vergangen und der Browser hat eine neue Anfrage für dieselbe Ressource initiiert. Zuerst prüft der Browser den HTTP-Cache und findet die vorherige Antwort. Leider kann der Browser die vorherige Antwort nicht verwenden, da die Antwort inzwischen abgelaufen ist. An dieser Stelle könnte der Browser eine neue Anfrage senden und die neue vollständige Antwort abrufen. Das ist jedoch ineffizient, denn wenn die Ressource nicht geändert wurde, gibt es keinen Grund, dieselben Informationen herunterzuladen, die sich bereits im Cache befinden. Dies ist das Problem, für das Validierungstokens, wie im ETag-Header angegeben, gelöst werden sollen. Der Server generiert ein beliebiges Token und gibt es zurück. Das ist normalerweise ein Hash oder ein anderer Fingerabdruck des Dateiinhalts. Der Browser muss nicht wissen, wie der Fingerabdruck generiert wird, sondern ihn nur bei der nächsten Anfrage an den Server senden. Wenn der Fingerabdruck immer noch der gleiche ist, hat sich die Ressource nicht geändert und der Browser kann den Download überspringen.

Wenn Sie ETag oder Last-Modified festlegen, wird die Anfrage zur erneuten Validierung viel effizienter. Sie lösen die Anfrageheader If-Modified-Since oder If-None-Match aus, die unter Anfrageheader erwähnt wurden.

Wenn ein ordnungsgemäß konfigurierter Webserver diese eingehenden Anfrageheader erkennt, kann er prüfen, ob die Version der Ressource, die sich bereits im HTTP-Cache des Browsers befindet, mit der neuesten Version auf dem Webserver übereinstimmt. Bei einer Übereinstimmung kann der Server mit der HTTP-Antwort 304 Not Modified antworten. Dies entspricht „Hey, verwende weiter, was du bereits hast“. Beim Senden dieses Antworttyps müssen nur sehr wenige Daten übertragen werden, sodass dies in der Regel viel schneller geht, als eine Kopie der tatsächlich angeforderten Ressource zurückzusenden.

Ein Diagramm, das zeigt, wie ein Client eine Ressource anfordert und der Server mit einem 304-Header antwortet.
Der Browser fordert /file vom Server an und fügt den Header If-None-Match ein, um den Server anzuweisen, die vollständige Datei nur zurückzugeben, wenn ETag der Datei auf dem Server nicht mit dem If-None-Match-Wert des Browsers übereinstimmt. In diesem Fall stimmten die beiden Werte überein und der Server gibt eine 304 Not Modified-Antwort mit einer Anleitung zurück, wie lange die Datei im Cache gespeichert werden soll (Cache-Control: max-age=120).

Zusammenfassung

Der HTTP-Cache ist eine effektive Methode zur Verbesserung der Lastleistung, da er unnötige Netzwerkanfragen reduziert. Es wird von allen Browsern unterstützt und erfordert nur wenig Einrichtung.

Die folgenden Cache-Control-Konfigurationen sind ein guter Anfang:

  • Cache-Control: no-cache für Ressourcen, die vor jeder Verwendung mit dem Server neu validiert werden sollten.
  • Cache-Control: no-store für Ressourcen, die niemals im Cache gespeichert werden sollen.
  • Cache-Control: max-age=31536000 für versionierte Ressourcen.

Mit dem Header ETag oder Last-Modified können Sie abgelaufene Cache-Ressourcen effizienter neu validieren.

Weitere Informationen

Wenn Sie über die Grundlagen der Verwendung des Cache-Control-Headers hinausgehen möchten, lesen Sie den Leitfaden Caching best practices & max-age gotchas von Jake Archibald.

Weitere Informationen dazu, wie Sie die Cache-Nutzung für wiederkehrende Besucher optimieren, finden Sie unter Cache leeren.

Anhang: Weitere Tipps

Wenn Sie mehr Zeit haben, finden Sie hier weitere Möglichkeiten, die Nutzung des HTTP-Cache zu optimieren:

  • Verwenden Sie konsistente URLs. Wenn Sie denselben Inhalt unter verschiedenen URLs bereitstellen, wird dieser Inhalt mehrmals abgerufen und gespeichert.
  • Minimieren Sie die Abwanderung. Wenn ein Teil einer Ressource (z. B. eine CSS-Datei) häufig aktualisiert wird, der Rest der Datei jedoch nicht (z. B. Bibliothekscode), sollten Sie den Code, der häufig aktualisiert wird, in eine separate Datei aufteilen und für den häufig aktualisierten Code eine Caching-Strategie mit kurzer Dauer und für den Code, der sich nicht oft ändert, eine lange Caching-Strategie verwenden.
  • Sehen Sie sich die neue stale-while-revalidate-Anweisung an, wenn ein gewisser Grad an Veralterung in Ihrer Cache-Control-Richtlinie akzeptabel ist.

Anhang: Flussdiagramm Cache-Control

Flussdiagramm

Anhang: Cache-Control-Beispiele

Cache-Control Wert Erklärung
max-age=86400 Die Antwort kann von Browsern und Zwischen-Caches bis zu 1 Tag lang (60 Sekunden × 60 Minuten × 24 Stunden) im Cache gespeichert werden.
private, max-age=600 Die Antwort kann vom Browser (jedoch nicht von Zwischencaches) bis zu 10 Minuten (60 Sekunden × 10 Minuten) im Cache gespeichert werden.
public, max-age=31536000 Die Antwort kann in einem beliebigen Cache ein Jahr lang gespeichert werden.
no-store Die Antwort darf nicht im Cache gespeichert werden und muss bei jeder Anfrage vollständig abgerufen werden.