Zapobiegaj niepotrzebnym żądaniam sieciowym dzięki pamięci podręcznej HTTP

Pobieranie zasobów przez sieć jest powolne i kosztowne:

  • Duże odpowiedzi wymagają wielu transferów w obie strony między przeglądarką a serwerem.
  • Strona nie załaduje się, dopóki wszystkie jej krytyczne zasoby nie zostaną w pełni pobrane.
  • Jeśli użytkownik Twojej witryny ma abonament na mobilną transmisję danych z ograniczoną ilością danych, każde niepotrzebne żądanie sieciowe jest jego stratą pieniędzy.

Jak uniknąć zbędnych żądań sieciowych? Pamięć podręczna HTTP przeglądarki to pierwsza linia obrony. Nie musi to być najbardziej efektywne i elastyczne rozwiązanie, a Ty masz ograniczoną kontrolę nad okresem przechowywania odpowiedzi w pamięci podręcznej, ale jest skuteczne, obsługiwane we wszystkich przeglądarkach i nie wymaga dużo pracy.

Ten przewodnik zawiera podstawowe informacje o efektywnej implementacji buforowania HTTP.

Zgodność z przeglądarką

Pamięć podręczna HTTP to ogólna nazwa zbioru interfejsów API platformy internetowej obsługiwanych we wszystkich przeglądarkach:

Cache-Control

Obsługa przeglądarek

  • Prawda
  • 12
  • Prawda
  • Prawda

Źródło

ETag

Obsługa przeglądarek

  • Prawda
  • 12
  • Prawda
  • Prawda

Źródło

Last-Modified

Obsługa przeglądarek

  • Prawda
  • 12
  • Prawda
  • Prawda

Źródło

Jak działa pamięć podręczna HTTP

Wszystkie żądania HTTP wysyłane przez przeglądarkę są najpierw kierowane do pamięci podręcznej przeglądarki w celu sprawdzenia, czy w pamięci podręcznej znajduje się prawidłowa odpowiedź, która może zostać wykorzystana do realizacji żądania. W przypadku dopasowania odpowiedź jest odczytywana z pamięci podręcznej, co eliminuje zarówno opóźnienia w sieci, jak i koszty przesyłania danych.

Działanie pamięci podręcznej HTTP zależy od kombinacji nagłówków żądań i nagłówków odpowiedzi. Idealnie zachowasz kontrolę zarówno nad kodem aplikacji internetowej, który określa nagłówki żądań, jak i konfiguracją serwera WWW, która określa nagłówki odpowiedzi.

Dokładniejsze omówienie znajdziesz w artykule Buforowanie HTTP w MDN.

Nagłówki żądań: pozostaw wartości domyślne (zwykle)

W żądaniach wychodzących z aplikacji internetowej należy pamiętać kilka ważnych nagłówków, ale gdy wysyła żądania, przeglądarka prawie zawsze konfiguruje je w Twoim imieniu. Nagłówki żądań, które wpływają na sprawdzanie aktualności, np. If-None-Match i If-Modified-Since, są wyświetlane zgodnie z interpretacją bieżących wartości w pamięci podręcznej HTTP.

To dobra wiadomość: możesz nadal umieszczać w kodzie HTML tagi takie jak <img src="my-image.png">, a przeglądarka będzie automatycznie i bez dodatkowych działań korzystać z pamięci podręcznej HTTP.

Nagłówki odpowiedzi: skonfiguruj serwer WWW

Najważniejszy element konfiguracji buforowania HTTP to nagłówki, które serwer WWW dodaje do każdej odpowiedzi wychodzącej. Te nagłówki wpływają na skuteczne zachowanie buforowania:

Cache-Control
Serwer może zwrócić dyrektywę Cache-Control, aby określić, jak i na jak długo przeglądarka i inne pośrednie pamięci podręczne mają buforować pojedynczą odpowiedź.
ETag.
Gdy przeglądarka znajdzie wygasłą odpowiedź w pamięci podręcznej, może wysłać do serwera mały token (zwykle jest to skrót zawartości pliku), aby sprawdzić, czy plik się zmienił. Jeśli serwer zwróci ten sam token, plik jest taki sam i nie trzeba go ponownie pobierać.
Last-Modified
Nagłówek służy do tego samego celu co tag ETag, ale do określenia, czy zasób się zmienił, zamiast strategii ETag opartej na treści korzysta ze strategii opartej na czasie.

Niektóre serwery WWW mają wbudowaną obsługę domyślnych ustawień tych nagłówków. Inne całkowicie pomijają nagłówki, chyba że je jednoznacznie skonfigurujesz. Szczegóły dotyczące konfigurowania nagłówków znacznie się różnią w zależności od używanego serwera WWW. Szczegółowe informacje znajdziesz w dokumentacji serwera.

Aby zaoszczędzić Ci trochę czasu, przygotowaliśmy te instrukcje konfigurowania kilku popularnych serwerów WWW:

Pominięcie nagłówka odpowiedzi Cache-Control nie wyłącza buforowania HTTP. Zamiast tego przeglądarki skutecznie odgadują, jaki typ zapisywania w pamięci podręcznej jest najlepszy w przypadku danego typu treści. Prawdopodobnie zależy Ci na większej kontroli, dlatego musisz poświęcić czas na skonfigurowanie nagłówków odpowiedzi.

Których wartości nagłówków odpowiedzi użyjesz?

Podczas konfigurowania nagłówków odpowiedzi serwera WWW musisz wziąć pod uwagę 2 ważne scenariusze.

Długotrwałe buforowanie adresów URL obsługujących wersje

Jak różne wersje adresów URL mogą pomóc w strategii buforowania
Korzystanie z wersjonowanych adresów URL jest dobrym rozwiązaniem, ponieważ ułatwia unieważnienie odpowiedzi z pamięci podręcznej.

Załóżmy, że serwer instruuje przeglądarki, aby buforowały plik CSS w pamięci podręcznej na rok (Cache-Control: max-age=31536000), ale projektant właśnie wprowadził aktualizację awaryjnej, którą musisz natychmiast wdrożyć. Jak powiadamiać przeglądarki o konieczności zaktualizowania „nieaktualnej” kopii pliku w pamięci podręcznej? Nie możesz, przynajmniej nie, nie możesz zmienić adresu URL zasobu.

Po tym, jak przeglądarka zapisze odpowiedź w pamięci podręcznej, wersja z pamięci podręcznej jest używana, dopóki nie przestanie być aktualna, zgodnie z metodą max-age lub expires, albo do momentu jej usunięcia z pamięci podręcznej z innego powodu, na przykład z innego powodu, na przykład przez użytkownika. W efekcie różni użytkownicy mogą wczytywać różne wersje pliku podczas tworzenia strony: użytkownicy, którzy właśnie pobrali zasób, korzystają z nowej wersji, ale użytkownicy, którzy zapisali w pamięci podręcznej wcześniejszą (ale nadal ważną) kopię, korzystają ze starszej (ale nadal prawidłowej) wersji.

Aby uzyskać zarówno zapisywanie w pamięci podręcznej po stronie klienta, jak i szybkie aktualizacje, możesz zmienić adres URL zasobu i wymusić pobranie nowej odpowiedzi po każdej zmianie treści. Zwykle robi się to, umieszczając odcisk cyfrowy pliku lub numer wersji w jego nazwie, np. style.x234dff.css.

Odpowiadając na prośby o adresy URL, które zawierają „odcisk palca” lub informacje o wersji, dodaj do swoich odpowiedzi atrybut Cache-Control: max-age=31536000.

Ustawienie tej wartości informuje przeglądarkę, że gdy będzie musiała wczytać ten sam adres URL w ciągu następnego roku (31 536 000 sekund, maksymalna obsługiwana wartość), może od razu użyć wartości z pamięci podręcznej HTTP bez konieczności wysyłania żądań sieciowych do serwera WWW. To świetnie, ponieważ od razu udało Ci się zwiększyć niezawodność i szybkość, które wynikają z unikania sieci.

Narzędzia do tworzenia, takie jak Webpack, mogą zautomatyzować proces przypisywania odcisków cyfrowych odcisków cyfrowych do adresów URL zasobów.

Ponowna weryfikacja serwera w przypadku adresów URL bez wersji

Nie wszystkie wczytane przez Ciebie adresy URL mają różne wersje. Być może nie można dodawać kroku kompilacji przed wdrożeniem aplikacji internetowej, więc nie można dodawać haszów do adresów URL zasobów. A każda aplikacja internetowa potrzebuje plików HTML, które prawie nigdy nie zawierają informacji o wersji. Nikt nie zechce skorzystać z Twojej aplikacji internetowej, jeśli będzie chciał pamiętać, że odwiedzany URL to https://example.com/index.34def12.html. Co więc możesz zrobić z tymi adresami URL?

Samo buforowanie HTTP nie jest wystarczające, aby całkowicie ominąć sieć. (Nie martw się – wkrótce dowiesz się więcej o skryptach service worker, które zapewniają dodatkową pomoc). Możesz jednak wykonać kilka czynności, aby żądania sieciowe były jak najszybsze i efektywne.

Te wartości Cache-Control pomogą Ci precyzyjnie określić, gdzie i w jaki sposób przechowywane są niewersowane adresy URL:

  • no-cache informuje przeglądarkę, że przed użyciem wersji adresu URL przechowywanej w pamięci podręcznej musi ona za każdym razem przeprowadzić ponowną weryfikację na serwerze.
  • no-store informuje przeglądarkę i inne pośrednie pamięci podręczne (np. sieci CDN), aby nigdy nie przechowywać żadnej wersji pliku.
  • private: przeglądarki mogą buforować plik, ale pośrednie pamięci podręczne nie.
  • public: odpowiedź może być przechowywana w każdej pamięci podręcznej.

Zobacz Załącznik: schemat blokowy Cache-Control, aby zwizualizować proces wybierania wartości Cache-Control do użycia. Cache-Control może też akceptować listę dyrektyw rozdzielonych przecinkami. Zobacz Załącznik: Cache-Control przykłady.

Pomóc może ustawienie ETag lub Last-Modified. Jak wspomnieliśmy w nagłówkach odpowiedzi, funkcje ETag i Last-Modified służą do tego samego celu: określenie, czy przeglądarka musi ponownie pobrać wygasły plik z pamięci podręcznej. Zalecamy użycie ETag, ponieważ jest on dokładniejszy.

Przykład elementu ETag

Załóżmy, że od rozpoczęcia pobierania minęło 120 sekund, a przeglądarka zainicjowała nowe żądanie dotyczące tego samego zasobu. Najpierw przeglądarka sprawdza pamięć podręczną HTTP i znajduje poprzednią odpowiedź. Przeglądarka nie może użyć poprzedniej odpowiedzi, ponieważ wygasła. W tym momencie przeglądarka może wysłać nowe żądanie i pobrać nową pełną odpowiedź. Jest to jednak nieefektywne, ponieważ jeśli zasób się nie zmienił, nie ma powodu, aby ponownie pobierać informacje, które już znajdują się w pamięci podręcznej.
Ten problem ma rozwiązywać tokeny weryfikacyjne ETag. Serwer generuje i zwraca dowolny token, który jest zwykle hasz lub inny odcisk cyfrowy zawartości pliku. Przeglądarka nie musi wiedzieć, jak jest generowany odcisk palca. Wystarczy, że wyśle ją do serwera w następnym żądaniu. Jeśli odcisk cyfrowy jest taki sam, oznacza to, że zasób nie uległ zmianie, a przeglądarka może pominąć pobieranie.

Ustawienie ETag lub Last-Modified znacznie usprawnia żądanie ponownej weryfikacji, ponieważ zezwala na uruchamianie nagłówków żądań If-Modified-Since lub If-None-Match wymienionych w nagłówkach żądań.

Gdy poprawnie skonfigurowany serwer WWW wykryje nagłówki żądań przychodzących, może sprawdzić, czy wersja zasobu, którą przeglądarka już znajduje w pamięci podręcznej HTTP, jest zgodna z najnowszą wersją na serwerze WWW. Jeśli do siebie pasują, serwer może odpowiedzieć, wysyłając odpowiedź HTTP 304 Not Modified, co jest odpowiednikiem polecenia „Hej, nadal korzystaj z tego, co już masz!”. Podczas wysyłania odpowiedzi tego typu można przesłać bardzo mało danych, więc zwykle jest to znacznie szybsze niż wysyłanie kopii rzeczywistego żądanego zasobu.

Diagram przedstawiający klienta żądającego zasobu, a serwer odpowiada za pomocą nagłówka 304.
Przeglądarka wysyła żądanie /file do serwera i zawiera nagłówek If-None-Match, który informuje serwer, że ma zwrócić pełny plik tylko wtedy, gdy ETag pliku na serwerze nie jest zgodny z wartością If-None-Match przeglądarki. W tym przypadku wartości są jednakowe, więc serwer zwraca odpowiedź 304 Not Modified z instrukcjami dotyczącymi czasu, przez jaki plik ma być przechowywany w pamięci podręcznej (Cache-Control: max-age=120).

Podsumowanie

Pamięć podręczna HTTP to skuteczny sposób na przyspieszenie wczytywania, ponieważ ogranicza liczbę zbędnych żądań sieciowych. Jest obsługiwana we wszystkich przeglądarkach i nie wymaga dużo pracy.

Warto zacząć od tych konfiguracji Cache-Control:

  • Cache-Control: no-cache dla zasobów, które powinny zostać ponownie zweryfikowane na serwerze przed każdym użyciem.
  • Cache-Control: no-store – zasoby, które nie powinny być przechowywane w pamięci podręcznej.
  • Cache-Control: max-age=31536000 dla zasobów z obsługą wersji.

Nagłówek ETag lub Last-Modified może pomóc w efektywniejszym potwierdzaniu wygasłych zasobów pamięci podręcznej.

Więcej informacji

Jeśli chcesz dowiedzieć się więcej niż tylko podstawowe informacje o korzystaniu z nagłówka Cache-Control, przeczytaj przewodnik Jake Archibalda na temat sprawdzonych metod dotyczących buforowania i maksymalnych wymagań dotyczących wieku.

Wskazówki dotyczące optymalizacji wykorzystania pamięci podręcznej przez powracających użytkowników znajdziesz w artykule Uwielbiaj pamięć podręczną.

Załącznik: więcej wskazówek

Jeśli masz więcej czasu, poniżej znajdziesz dodatkowe sposoby optymalizacji wykorzystania pamięci podręcznej HTTP:

  • Używaj spójnych adresów URL. Jeśli udostępniasz te same treści pod różnymi adresami URL, przeglądarka wielokrotnie je pobiera i przechowuje.
  • Ogranicz liczbę rezygnacji. Jeśli część zasobu (np. plik CSS) jest często aktualizowana, a reszta pliku nie (tak jak w przypadku kodu biblioteki), rozważ podzielenie często aktualizowanego kodu na oddzielny plik i zastosowanie krótkotrwałej strategii buforowania w przypadku często aktualizowanego kodu oraz strategii o długim czasie przechowywania w przypadku kodu, który rzadko się zmienia.
  • Jeśli zasada Cache-Control akceptuje pewien poziom nieaktualności, rozważ zastosowanie nowej dyrektywy stale-while-revalidate .

Dodatek: schemat blokowy typu Cache-Control

Schemat blokowy
Proces definiowania nagłówków Cache-Control.

Dodatek: Cache-Control przykładów

Wartość: Cache-Control Wyjaśnienie
max-age=86400 Odpowiedź może być przechowywana w pamięci podręcznej przeglądarek i pośrednich pamięci podręcznych przez maksymalnie 1 dzień (60 sekund x 60 minut x 24 godziny).
private, max-age=600 Odpowiedź może być przechowywana w pamięci podręcznej przeglądarki, ale nie w pamięci podręcznej pośredniej, przez maksymalnie 10 minut (60 sekund x 10 minut).
public, max-age=31536000 Odpowiedź można przechowywać w dowolnej pamięci podręcznej przez rok.
no-store Odpowiedź nie może być przechowywana w pamięci podręcznej i musi być pobierana w całości przy każdym żądaniu.