Unnötige Netzwerkanfragen mit dem HTTP-Cache vermeiden

Das Abrufen von Ressourcen über das Netzwerk ist sowohl langsam als auch teuer:

  • Große Antworten erfordern viele Umläufe zwischen dem Browser und dem Server.
  • Ihre Seite wird erst geladen, wenn alle wichtigen Ressourcen vollständig heruntergeladen wurden.
  • Wenn eine Person mit einem Tarif für mobile Daten auf Ihre Website zugreift, ist jede unnötige Netzwerkanfrage Geldverschwendung.

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

In diesem Leitfaden werden die Grundlagen einer effektiven HTTP-Caching-Implementierung beschrieben.

Browserkompatibilität

Es gibt eigentlich keine einzelne API namens HTTP-Cache. 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 im Cache eine gültige Antwort vorhanden ist, die zum Ausführen der Anfrage verwendet werden kann. Bei einer Übereinstimmung wird die Antwort aus dem Cache gelesen, wodurch sowohl die Netzwerklatenz als auch die Datenkosten entfallen, die bei der Übertragung anfallen.

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

Im Artikel HTTP-Caching von MDN findest du eine ausführlichere konzeptionelle Übersicht.

Anfrageheader: (normalerweise) Standardeinstellungen beibehalten

Es gibt zwar einige wichtige Header, die in den ausgehenden Anfragen Ihrer Webanwendung enthalten sein sollten, aber der Browser legt sie bei Anfragen fast immer für Sie fest. Anfrageheader, die sich auf die Aktualitätsprüfung auswirken, wie If-None-Match und If-Modified-Since, werden nur dann angezeigt, wenn der Browser die aktuellen Werte im HTTP-Cache versteht.

Das ist eine gute Nachricht: Sie können weiterhin Tags wie <img src="my-image.png"> in Ihren HTML-Code einfügen und der Browser übernimmt das HTTP-Caching für Sie 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 fließen alle in ein effektives Caching-Verhalten ein:

  • Cache-Control: Der Server kann eine Cache-Control-Anweisung zurückgeben, um anzugeben, 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 ermitteln, ob eine Ressource geändert wurde, im Gegensatz zur inhaltsbasierten Strategie von ETag.

Einige Webserver unterstützen die standardmäßige Festlegung dieser Header. Andere lassen die Header gänzlich aus, sofern Sie sie nicht explizit konfigurieren. Die spezifischen Details zur Konfiguration von Headern variieren je nach verwendetem Webserver sehr stark. Genauere Informationen finden Sie in der Dokumentation Ihres Servers.

Hier finden Sie Anweisungen zur Konfiguration einiger häufig verwendeter Webserver:

Durch das Weglassen des Cache-Control-Antwortheaders wird das HTTP-Caching nicht deaktiviert. Stattdessen schätzen Browser, welche Art von Caching-Verhalten 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 Werte für den Antwortheader sollten Sie verwenden?

Es gibt zwei wichtige Szenarien, die Sie beim Konfigurieren der Antwortheader Ihres Webservers behandeln sollten.

Langlebiges Caching für versionierte URLs

Wie sich versionierte URLs für Ihre Caching-Strategie eignen
Versionierte URLs sind empfehlenswert, 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 einführen müssen. Wie informieren Sie Browser darüber, dass die „veraltete“ im Cache gespeicherte Kopie der Datei aktualisiert wird? 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 so lange 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 seinen Browsercache löscht. Daher können verschiedene 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 nutzen Sie das Beste aus beiden Welten: clientseitiges Caching und schnelle Updates? Sie ändern die URL der Ressource und zwingen den Nutzer, die neue Antwort herunterzuladen, wenn sich ihr Inhalt ändert. Dazu betten Sie in der Regel einen Fingerabdruck der Datei oder eine Versionsnummer in den 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, wenn im Laufe des nächsten Jahres (31.536.000 Sekunden; der maximal unterstützte Wert) dieselbe URL laden muss, den Wert im HTTP-Cache sofort verwenden kann, 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 Version

Leider haben nicht alle URLs, die Sie laden, versionierte URLs. Möglicherweise können Sie vor der Bereitstellung Ihrer Webanwendung keinen Build-Schritt einbinden und somit Ihren Asset-URLs auch keine Hashes hinzufügen. Jede Webanwendung benötigt HTML-Dateien. Diese Dateien enthalten (so gut wie!) nie Versionsinformationen, da sich niemand Ihre Webanwendung verwenden würde, 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 du deine Niederlage eingestehen musst. HTTP-Caching allein reicht nicht aus, um das Netzwerk vollständig zu umgehen. Keine Sorge – in Kürze erfahren Sie mehr über Service Worker, die uns bei der Lösung des Problems unterstützen. Es gibt jedoch einige Schritte, mit denen Sie dafür sorgen können, dass Netzwerkanfragen so schnell und effizient wie möglich ausgeführt werden.

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

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

Im Anhang: Cache-Control-Flussdiagramm wird der Entscheidungsprozess für Cache-Control-Wert(e) veranschaulicht. 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: Ermitteln, 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. Der Browser kann die vorherige Antwort leider nicht verwenden, da die Antwort jetzt abgelaufen ist. An dieser Stelle könnte der Browser eine neue Anfrage senden und die neue vollständige Antwort abrufen. Dies ist jedoch ineffizient, denn wenn die Ressource nicht geändert wurde, gibt es keinen Grund, die 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 in der Regel ein Hash oder ein anderer Fingerabdruck des Inhalts der Datei. Der Browser muss nicht wissen, wie der Fingerabdruck generiert wurde. Er muss ihn nur bei der nächsten Anfrage an den Server senden. Wenn der Fingerabdruck immer noch derselbe 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 wesentlich effizienter. Sie lösen schließlich die Anfrageheader If-Modified-Since oder If-None-Match aus, die unter Anfrageheader aufgeführt sind.

Wenn ein ordnungsgemäß konfigurierter Webserver diese eingehenden Anfrageheader sieht, 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 das, 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 mit einem Client, der eine Ressource anfordert, und der Server, der 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 dann zurückzugeben, wenn der ETag der Datei auf dem Server nicht mit dem If-None-Match-Wert des Browsers übereinstimmt. In diesem Fall stimmten die beiden Werte überein. Daher gibt der Server 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 Möglichkeit, die Lastleistung zu verbessern, da er unnötige Netzwerkanfragen reduziert. Es wird von allen Browsern unterstützt und ist im Handumdrehen eingerichtet.

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

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

Und mit dem ETag- oder Last-Modified-Header 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 Jake Archibalds Leitfaden Caching Best Practices und Max-age Gotchas.

Unter Cache leeren erfahren Sie, wie Sie die Cache-Nutzung für wiederkehrende Besucher optimieren.

Anhang: Weitere Tipps

Wenn Sie mehr Zeit haben, können Sie die Nutzung des HTTP-Cache so optimieren:

  • Verwenden Sie konsistente URLs. Wenn Sie dieselben Inhalte unter verschiedenen URLs bereitstellen, werden diese Inhalte 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 (z. B. Bibliothekscode), empfiehlt es sich, den häufig aktualisierten Code in eine separate Datei aufzuteilen 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 zu verwenden.
  • Sehen Sie sich die neue stale-while-revalidate-Anweisung an, wenn ein Grad an Veralterung in Ihrer Cache-Control-Richtlinie akzeptabel ist.

Anhang: Flussdiagramm für Cache-Control

Flussdiagramm

Anhang: Cache-Control Beispiele

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