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

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

  • Duże odpowiedzi wymagają przesyłania wielu informacji między przeglądarką a serwerem.
  • Strona załaduje się dopiero wtedy, gdy wszystkie krytyczne zasoby nie zostaną w pełni pobrane.
  • Jeśli użytkownik korzysta z Twojej witryny, mając ograniczony pakiet mobilnej transmisji danych, każde niepotrzebne żądanie sieciowe to strata pieniędzy.

Jak możesz uniknąć niepotrzebnych żądań sieciowych? Pamięć podręczna HTTP przeglądarki to Twoja pierwsza linia obrony. Nie musi to być najbardziej zaawansowane i elastyczne podejście. Masz ograniczoną kontrolę nad czasem przechowywania odpowiedzi w pamięci podręcznej, ale jest skuteczne, obsługiwane przez wszystkie przeglądarki i nie wymaga wiele pracy.

Ten przewodnik zawiera podstawowe informacje o skutecznej implementacji buforowania HTTP.

Zgodność z przeglądarką

W rzeczywistości nie istnieje pojedynczy interfejs API o nazwie HTTP Cache. Jest to ogólna nazwa zbioru interfejsów API platformy internetowej. Te interfejsy API są obsługiwane 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 jej pamięci podręcznej w celu sprawdzenia, czy w pamięci podręcznej znajduje się prawidłowa odpowiedź, której można użyć 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 danych związane z przesyłaniem.

Zachowanie pamięci podręcznej HTTP jest kontrolowane przez kombinację nagłówków żądań i nagłówków odpowiedzi. W idealnym scenariuszu będziesz mieć kontrolę zarówno nad kodem swojej aplikacji internetowej (określającej nagłówki żądań), jak i konfiguracją serwera WWW (która określa nagłówki odpowiedzi).

Bardziej szczegółowe omówienie zagadnień technicznych znajdziesz w artykule Buforowanie HTTP w MDN.

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

Istnieje wiele ważnych nagłówków, które powinny być uwzględnione w żądaniach wychodzących aplikacji internetowej, ale przeglądarka prawie zawsze ustawia je w Twoim imieniu, gdy wysyła żądania. Nagłówki żądań, które wpływają na sprawdzanie aktualności wyników, takie jak If-None-Match i If-Modified-Since, pojawiają się, jeśli przeglądarka zrozumie bieżące 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 automatycznie zajmie się buforowaniem HTTP bez dodatkowych działań z Twojej strony.

Nagłówki odpowiedzi: skonfiguruj serwer WWW

Częścią konfiguracji buforowania HTTP, która ma największe znaczenie, są nagłówki dodawane przez serwer WWW do każdej odpowiedzi wychodzącej. Te nagłówki mają wpływ na skuteczne działanie buforowania:

  • Cache-Control. Serwer może zwrócić dyrektywę Cache-Control, aby określić, w jaki sposób i jak długo przeglądarka i inne pośrednie pamięci podręczne mają przechowywać daną odpowiedź w pamięci podręcznej.
  • ETag. Gdy przeglądarka znajdzie nieaktualną odpowiedź w pamięci podręcznej, może wysłać do serwera niewielki token (zwykle skrót zawartości pliku), aby sprawdzić, czy plik nie uległ zmianie. Jeśli serwer zwróci ten sam token, plik jest taki sam i nie ma potrzeby ponownego pobierania go.
  • Last-Modified. Ten nagłówek ma taki sam cel jak nagłówek ETag, ale do określenia, czy zasób się zmienił, do określania, czy zasób uległ zmianie, używana jest strategia oparta na treści (ETag).

Niektóre serwery WWW mają wbudowaną obsługę domyślnego ustawiania nagłówków, a inne całkowicie je wyłączają, chyba że zostaną one przez Ciebie skonfigurowane. Szczegółowe informacje o konfigurowaniu nagłówków różnią się w zależności od używanego serwera WWW. Szczegółowe informacje znajdziesz w dokumentacji serwera.

Aby uniknąć konieczności wyszukiwania, zapoznaj się z poniższymi instrukcjami konfigurowania kilku popularnych serwerów WWW:

Pominięcie nagłówka odpowiedzi Cache-Control nie wyłącza buforowania HTTP. Zamiast tego przeglądarki skutecznie odgadną, jaki typ zachowania w pamięci podręcznej jest najbardziej sensowny w przypadku danego typu treści. Możliwe, że potrzebujesz większej kontroli nad tymi ofertami, więc poświęć trochę czasu na skonfigurowanie nagłówków odpowiedzi.

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

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

Długotrwałe buforowanie w przypadku adresów URL z obsługą wersji

Jak adresy URL z obsługą wersji mogą pomóc w strategii buforowania
Warto używać wersji adresów URL, ponieważ ułatwiają unieważnianie odpowiedzi zapisanych w pamięci podręcznej.

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

Gdy przeglądarka zapisze odpowiedź w pamięci podręcznej, używana jest wersja z pamięci podręcznej, dopóki nie będzie już aktualna (zgodnie z zasadami max-age lub expires) albo do czasu usunięcia jej z pamięci podręcznej z innego powodu, na przykład przez wyczyszczenie pamięci podręcznej przeglądarki. W efekcie podczas tworzenia strony różni użytkownicy mogą korzystać z różnych wersji pliku. Użytkownicy, którzy właśnie pobrali zasób, korzystają z nowej wersji, a użytkownicy, którzy zapisali wcześniejszą (ale nadal ważną) kopię w pamięci podręcznej, korzystają ze starszej wersji odpowiedzi.

Jak możesz korzystać z obu rozwiązań: buforowania po stronie klienta i szybkich aktualizacji? Gdy zmienisz adres URL zasobu, użytkownik będzie musiał pobrać nową odpowiedź, gdy zmieni się jego zawartość. Zwykle można to zrobić, umieszczając w nazwie pliku odcisk cyfrowy pliku lub numer wersji, na przykład style.x234dff.css.

Gdy odpowiadasz na prośby o adresy URL, które zawierają „odcisk cyfrowy” lub informacje o wersji, a które treści nigdy nie powinny być zmieniane, dodaj do swoich odpowiedzi Cache-Control: max-age=31536000.

Ustawienie tej wartości informuje przeglądarkę, że gdy musi wczytać ten sam adres URL w ciągu następnego roku (31 536 000 sekund; maksymalna obsługiwana wartość), może natychmiast użyć wartości z pamięci podręcznej HTTP bez konieczności wysyłania żądania sieciowego do serwera WWW. To świetnie—od razu przyzwyczaiłeś się do niezawodności i szybkości, które wiążą się z unikaniem sieci.

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

Ponowna weryfikacja serwera adresów URL bez wersji

Niestety nie wszystkie wczytywane adresy URL mają wersję. Być może nie możesz dodać etapu kompilacji przed wdrożeniem swojej aplikacji internetowej, więc nie możesz dodawać haszy do adresów URL zasobów. A każda aplikacja internetowa wymaga plików HTML – prawie nigdy nie będą one zawierały informacji o wersji, ponieważ nikt nie będzie odczuć używania Twojej aplikacji internetowej, jeśli musi pamiętać, że adres URL, który należy odwiedzić, to https://example.com/index.34def12.html. Co więc możesz zrobić z tymi adresami URL?

W takiej sytuacji trzeba przyznać się do porażki. Samo buforowanie HTTP nie jest wystarczająco wydajne, aby całkowicie ominąć sieć. (Nie martw się – wkrótce dowiesz się więcej o usługodawcach, którzy dadzą nam potrzebne wsparcie). Możesz jednak wykonać kilka czynności, aby zapewnić jak najszybsze wysyłanie żądań sieciowych.

Te wartości Cache-Control pomogą Ci doprecyzować, gdzie i w jaki sposób adresy URL bez wersji są zapisywane w pamięci podręcznej:

  • no-cache. To informacja dla przeglądarki, że przed użyciem wersji adresu URL z pamięci podręcznej przeglądarki musi ona za każdym razem przeprowadzić ponowną weryfikację z serwerem.
  • no-store. To sprawia, że przeglądarka i inne pośrednie pamięci podręczne (np. CDN) nigdy nie przechowują żadnej wersji pliku.
  • private. Przeglądarki mogą zapisywać plik w pamięci podręcznej, ale pośrednie pamięci podręczne nie mogą tego zrobić.
  • public. Odpowiedź może być przechowywana w dowolnej pamięci podręcznej.

Aby zwizualizować proces wybierania wartości Cache-Control do użycia, zapoznaj się z Załącznikiem: schemat blokowy Cache-Control. Pole Cache-Control może też zawierać listę dyrektyw oddzielonych przecinkami. Zobacz Dodatek (przykłady: Cache-Control).

Pomocne może też być ustawienie ETag lub Last-Modified. Jak wspomnieliśmy w sekcji Nagłówki odpowiedzi, atrybuty ETag i Last-Modified służą do tego samego celu: określania, czy przeglądarka musi ponownie pobrać wygasły plik z pamięci podręcznej. Zalecamy użycie metody ETag, ponieważ jest ona dokładniejsza.

Przykład ETag

Przyjmijmy, że od momentu początkowego pobrania minęło 120 sekund, a przeglądarka zainicjowała nowe żądanie 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 pobierać te same informacje, które są już w pamięci podręcznej.

To problem, który mają rozwiązać tokeny weryfikacyjne, jak określono w nagłówku ETag. Serwer generuje i zwraca dowolny token, który zwykle jest haszem lub innym odciskiem cyfrowym treści pliku. Przeglądarka nie musi wiedzieć, w jaki sposób jest generowany odcisk cyfrowy – musi tylko wysłać go do serwera przy następnym żądaniu. Jeśli odcisk cyfrowy jest taki sam, zasób nie uległ zmianie i przeglądarka może pominąć pobieranie.

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

Gdy poprawnie skonfigurowany serwer WWW rozpozna nagłówki żądań przychodzących, może sprawdzić, czy wersja zasobu, którą przeglądarka ma już w swojej pamięci podręcznej HTTP, jest zgodna z najnowszą wersją na serwerze WWW. Jeśli uda się dopasować, serwer może odpowiedzieć HTTP 304 Not Modified, co jest odpowiednikiem polecenia „OK, kontynuuj korzystanie z tego, co już masz!”. Wysyłając tego typu odpowiedź, jest bardzo mało danych do przesłania, więc zwykle trwa to znacznie krócej niż odesłanie kopii rzeczywistego zasobu, którego dotyczy żądanie.

Wizualizacja, która przedstawia klienta żądającego zasobu i serwer odpowiadając za pomocą nagłówka 304.
Przeglądarka wysyła do serwera żądanie /file i zawiera nagłówek If-None-Match informujący serwer, że ma zwracać pełny plik tylko wtedy, gdy ETag pliku na serwerze nie pasuje do wartości If-None-Match przeglądarki. W tym przypadku 2 wartości były zgodne, więc serwer zwraca odpowiedź 304 Not Modified z instrukcjami, jak długo plik powinien być przechowywany w pamięci podręcznej (Cache-Control: max-age=120).

Podsumowanie

Pamięć podręczna HTTP to skuteczny sposób na zwiększenie wydajności wczytywania, ponieważ zredukuje się liczba niepotrzebnych żądań sieciowych. Jest ono obsługiwane we wszystkich przeglądarkach, a jego konfiguracja nie wymaga zbyt wiele 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 w przypadku zasobów, które nigdy nie powinny być przechowywane w pamięci podręcznej.
  • Cache-Control: max-age=31536000 na potrzeby zasobów z obsługą wersji.

Nagłówek ETag lub Last-Modified może też pomóc w skuteczniejszym ponownym weryfikowaniu zasobów pamięci podręcznej, których ważność wygasła.

Więcej informacji

Jeśli chcesz dowiedzieć się więcej o korzystaniu z nagłówka Cache-Control, zapoznaj się z przewodnikiem Jake'a Archibalda na temat sprawdzonych metod dotyczących buforowania i max-age gotchas (w języku angielskim).

Przeczytaj sekcję Pokochaj pamięć podręczną, aby dowiedzieć się, jak zoptymalizować wykorzystanie pamięci podręcznej pod kątem powracających użytkowników.

Dodatek: więcej wskazówek

Jeśli masz więcej czasu, oto kolejne sposoby optymalizacji wykorzystania pamięci podręcznej HTTP:

  • Używaj spójnych adresów URL. Jeśli te same treści są wyświetlane pod różnymi adresami URL, będą one wielokrotnie pobierane i przechowywane.
  • Minimalizuj liczbę rezygnacji. Jeśli część zasobu (np. plik CSS) jest często aktualizowana, a reszta pliku nie (np. kod biblioteki), rozważ podzielenie często aktualizowanego kodu do osobnego pliku i zastosowanie krótkotrwałej strategii buforowania dla często aktualizowanego kodu oraz długiego czasu przechowywania kodu, który rzadko się zmienia.
  • Zapoznaj się z nową dyrektywą stale-while-revalidate, jeśli zasady Cache-Control dopuszczają pewien stopień nieaktualności.

Załącznik: schemat blokowy Cache-Control

Schemat blokowy
Proces decyzyjny dotyczący ustawienia nagłówków Cache-Control.

Dodatek (przykłady: Cache-Control)

Wartość: Cache-Control Wyjaśnienie
max-age=86400 Odpowiedź może być przechowywana w pamięci podręcznej przeglądarek i pośredniej pamięci podręcznej 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 pośredniej pamięci podręcznej) przez maksymalnie 10 minut (60 sekund x 10 minut).
public, max-age=31536000 Odpowiedź może być przechowywana w dowolnej pamięci podręcznej przez 1 rok.
no-store Odpowiedzi nie można przechowywać w pamięci podręcznej i musi być pobierana w całości przy każdym żądaniu.