Unnötige Netzwerkanfragen mit dem HTTP-Cache vermeiden

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

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

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

In diesem Leitfaden werden die Grundlagen einer effektiven HTTP-Caching-Implementierung erläutert.

Browser-Kompatibilität

Es gibt keine einzelne API namens HTTP-Cache. Es ist der allgemeine Name für eine Sammlung von Webplattform-APIs. Diese APIs werden in allen Browsern unterstützt:

Cache-Control

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

ETag

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

Last-Modified

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

Funktionsweise des HTTP-Cache

Alle HTTP-Anfragen, die der Browser stellt, werden zuerst an den Browser-Cache weitergeleitet, um zu prüfen, ob eine gültige im Cache gespeicherte Antwort vorhanden ist, die zur Erfüllung der Anfrage verwendet werden kann. Wenn eine Übereinstimmung gefunden wird, wird die Antwort aus dem Cache gelesen. Dadurch werden sowohl die Netzwerklatenz als auch die Datenkosten für die Übertragung vermieden.

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

Eine ausführlichere konzeptionelle Übersicht finden Sie im MDN-Artikel HTTP-Caching.

Anfrageheader: Behalten Sie die Standardeinstellungen bei (normalerweise).

Es gibt eine Reihe wichtiger Header, die in den ausgehenden Anfragen Ihrer Web-App enthalten sein sollten. Der Browser kümmert sich jedoch fast immer darum, sie in Ihrem Namen festzulegen, wenn er Anfragen stellt. Anfrageheader, die sich auf die Prüfung der Aktualität auswirken, z. B. If-None-Match und If-Modified-Since, werden basierend auf dem Verständnis des Browsers der aktuellen Werte im HTTP-Cache angezeigt.

Das sind gute Nachrichten: Sie können weiterhin Tags wie <img src="my-image.png"> in Ihren HTML-Code einfügen und der Browser kümmert sich automatisch um das HTTP-Caching, ohne dass Sie etwas dafür tun müssen.

Antwortheader: Webserver konfigurieren

Der wichtigste Teil der HTTP-Caching-Einrichtung sind die Header, die Ihr Webserver jeder ausgehenden Antwort hinzufügt. Die folgenden Header beeinflussen das Caching-Verhalten:

  • 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 (normalerweise einen Hash des Dateiinhalts) an den Server senden, um zu prüfen, ob sich die Datei geändert hat. 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 festzustellen, ob sich eine Ressource geändert hat, im Gegensatz zur inhaltsbasierten Strategie von ETag.

Einige Webserver unterstützen das Festlegen dieser Header standardmäßig, während andere die Header vollständig weglassen, sofern Sie sie nicht explizit konfigurieren. Die genauen Details zur Konfiguration von Headern variieren stark je nach verwendetem Webserver. Genaue Informationen finden Sie in der Dokumentation Ihres Servers.

Damit Sie nicht lange suchen müssen, finden Sie hier Anleitungen zum Konfigurieren einiger gängiger Webserver:

Wenn Sie den Antwortheader Cache-Control weglassen, wird das HTTP-Caching nicht deaktiviert. Stattdessen raten Browser effektiv, welche Art von Caching-Verhalten für einen bestimmten Inhaltstyp am sinnvollsten ist. Wahrscheinlich möchten Sie mehr Kontrolle, als diese Option bietet. Nehmen Sie sich also die Zeit, Ihre Antwortheader zu konfigurieren.

Welche Antwortheaderwerte sollten Sie verwenden?

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

Langlebiges Caching für versionierte URLs

Wie versionierte URLs Ihre Caching-Strategie unterstützen können
Versionierte URLs sind eine gute Praxis, da sie es einfacher machen, im Cache gespeicherte Antworten ungültig zu machen.

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 vorgenommen, das Sie sofort bereitstellen müssen. Wie benachrichtigen Sie Browser, die „veraltete“ im Cache gespeicherte Kopie der Datei zu aktualisieren? 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 nicht mehr aktuell ist (gemäß max-age oder expires) oder bis sie aus einem anderen Grund aus dem Cache entfernt wird, z. B. weil der Nutzer den Browser-Cache leert. Das kann dazu führen, dass 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 immer noch gültige) Kopie im Cache gespeichert haben, eine ältere Version der Antwort verwenden.

Wie können Sie das Beste aus beiden Welten herausholen: clientseitiges Caching und schnelle Updates? Sie ändern die URL der Ressource und erzwingen, dass der Nutzer die neue Antwort herunterlädt, wenn sich der Inhalt ändert. In der Regel betten Sie dazu einen Fingerabdruck der Datei oder eine Versionsnummer in den Dateinamen ein, z. B. style.x234dff.css.

Wenn du auf Anfragen für URLs antwortest, die „Fingerabdruck“ oder Versionsinformationen enthalten und deren Inhalt sich nie ändern soll, füge deinen Antworten Cache-Control: max-age=31536000 hinzu.

Wenn Sie diesen Wert festlegen, weiß der Browser, dass er, wenn er dieselbe URL innerhalb des nächsten Jahres (31.536.000 Sekunden; der maximal unterstützte Wert) laden muss, sofort den Wert im HTTP-Cache verwenden kann, ohne eine Netzwerkanfrage an Ihren Webserver senden zu müssen. Das ist großartig – Sie profitieren sofort von der Zuverlässigkeit und Geschwindigkeit, die sich daraus ergeben, dass Sie das Netzwerk umgehen.

Mit Build-Tools wie webpack lässt sich der Prozess der Zuweisung von Hash-Fingerabdrücken zu Ihren Asset-URLs automatisieren.

Server-Revalidierung für nicht versionierte URLs

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

In diesem Szenario müssen Sie sich geschlagen geben. HTTP-Caching allein reicht nicht aus, um das Netzwerk vollständig zu umgehen. Keine Sorge, bald lernen Sie Service Worker kennen, die Ihnen die nötige Unterstützung bieten, um das Blatt zu Ihren Gunsten zu wenden. Es gibt jedoch einige Schritte, mit denen Sie dafür sorgen können, dass Netzwerkanfragen so schnell und effizient wie möglich sind.

Mit den folgenden Cache-Control-Werten können Sie genau festlegen, wo und wie URLs ohne Versionsangabe im Cache gespeichert werden:

  • no-cache. Dadurch wird der Browser angewiesen, vor der Verwendung einer im Cache gespeicherten Version der URL jedes Mal eine erneute Validierung mit dem Server durchzuführen.
  • no-store. Dadurch werden der Browser und andere Zwischen-Caches (z. B. CDNs) angewiesen, keine Version der Datei zu speichern.
  • private: Browser können die Datei im Cache speichern, Zwischen-Caches jedoch nicht.
  • public. Die Antwort kann von jedem Cache gespeichert werden.

Im Anhang: Cache-Control-Flussdiagramm finden Sie eine Visualisierung des Prozesses, mit dem Sie entscheiden, welche Cache-Control-Werte verwendet werden sollen. Cache-Control kann auch eine durch Kommas getrennte Liste von Anweisungen akzeptieren. Siehe Anhang: Cache-Control-Beispiele.

Das Festlegen von ETag oder Last-Modified kann ebenfalls hilfreich sein. Wie unter Antwortheader erwähnt, dienen ETag und Last-Modified demselben Zweck: Sie bestimmen, ob der Browser eine abgelaufene im Cache gespeicherte Datei noch einmal herunterladen muss. Wir empfehlen die Verwendung von ETag, da diese Methode 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 sie abgelaufen ist. An diesem Punkt könnte der Browser eine neue Anfrage senden und die neue vollständige Antwort abrufen. Das ist jedoch ineffizient, da es keinen Grund gibt, dieselben Informationen, die sich bereits im Cache befinden, herunterzuladen, wenn sich die Ressource nicht geändert hat.

Dieses Problem soll mit Validierungstokens gelöst werden, die im Header ETag angegeben sind. Der Server generiert ein beliebiges Token und gibt es zurück. In der Regel handelt es sich dabei um einen Hash oder einen anderen Fingerabdruck des Dateiinhalts. Der Browser muss nicht wissen, wie der Fingerabdruck generiert wird. 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, da die Anfrageheader If-Modified-Since oder If-None-Match ausgelöst werden, die unter Anfrageheader erwähnt werden.

Wenn ein ordnungsgemäß konfigurierter Webserver diese eingehenden Anfrageheader sieht, kann er prüfen, ob die Version der Ressource, die der Browser bereits in seinem HTTP-Cache hat, mit der aktuellen Version auf dem Webserver übereinstimmt. Wenn es eine Übereinstimmung gibt, kann der Server mit einer HTTP-Antwort 304 Not Modified antworten, was so viel bedeutet wie „Hey, verwende einfach weiter, was du schon hast!“. Beim Senden dieser Art von Antwort müssen nur sehr wenige Daten übertragen werden. Daher ist dies in der Regel viel schneller, als eine Kopie der angeforderten Ressource zurückzusenden.

Eine Visualisierung eines Clients, der eine Ressource anfordert, und des Servers, der mit einem 304-Header antwortet.
Der Browser fordert /file vom Server an und fügt den Header If-None-Match hinzu, 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 stimmen die beiden Werte überein. Der Server gibt also eine 304 Not Modified-Antwort mit Anweisungen dazu zurück, wie lange die Datei noch im Cache gespeichert werden soll (Cache-Control: max-age=120).

Zusammenfassung

Der HTTP-Cache ist eine effektive Möglichkeit, die Ladeleistung zu verbessern, da er unnötige Netzwerkanfragen reduziert. Sie wird von allen Browsern unterstützt und ist einfach einzurichten.

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 sollen.
  • Cache-Control: no-store für Ressourcen, die nie 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 mehr als nur die Grundlagen des Cache-Control-Headers kennenlernen möchten, lesen Sie den Leitfaden Caching best practices and max-age gotchas von Jake Archibald.

Unter Love your cache finden Sie eine Anleitung, wie Sie die Cache-Nutzung für wiederkehrende Besucher optimieren können.

Anhang: Weitere Tipps

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

  • Verwenden Sie einheitliche URLs. Wenn Sie dieselben Inhalte unter verschiedenen URLs bereitstellen, werden diese Inhalte mehrmals abgerufen und gespeichert.
  • Abwanderung minimieren Wenn ein Teil einer Ressource (z. B. eine CSS-Datei) häufig aktualisiert wird, der Rest der Datei (z. B. Bibliothekscode) jedoch nicht, sollten Sie den häufig aktualisierten Code in eine separate Datei aufteilen und eine Caching-Strategie mit kurzer Dauer für den häufig aktualisierten Code und eine Caching-Strategie mit langer Dauer für den Code verwenden, der sich nicht oft ändert.
  • Wenn ein gewisser Grad an Veraltung in deiner Cache-Control-Richtlinie akzeptabel ist, kannst du die neue stale-while-revalidate-Anweisung verwenden.

Anhang: Cache-Control-Flussdiagramm

Flussdiagramm
Entscheidungsprozess zum Festlegen der Cache-Control-Header.

Anhang: Cache-Control Beispiele

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