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 danych 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 korzysta z Twojej witryny z ograniczonym abonamentem na mobilną transmisję danych, każde niepotrzebne żądanie do sieci jest jej marnowaniem.

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ą

Tak naprawdę nie ma jednego interfejsu API o nazwie HTTP Cache. To ogólna nazwa zbioru interfejsów API platform internetowych. Te interfejsy API są obsługiwane we wszystkich przeglądarkach:

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, aby sprawdzić, czy w pamięci podręcznej znajduje się prawidłowa odpowiedź, która może pomóc je zrealizować. Jeśli do siebie pasują, odpowiedź jest odczytywana z pamięci podręcznej, co eliminuje zarówno opóźnienia sieciowe, jak i koszty danych związane z przesyłaniem.

Działanie pamięci podręcznej HTTP zależy od kombinacji nagłówków żądań i nagłówków odpowiedzi. W idealnym scenariuszu będziesz mieć kontrolę nad kodem aplikacji internetowej (która określa nagłówki żądań) i konfiguracją serwera WWW (która określa nagłówki odpowiedzi).

Dokładniejsze omówienie zagadnienia znajdziesz w artykule na temat buforowania HTTP w MDN.

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

Chociaż w żądaniach wychodzących aplikacji internetowej należy uwzględnić wiele ważnych nagłówków, to przeglądarka prawie zawsze konfiguruje je w Twoim imieniu, gdy wysyła żądania. Nagłówki żądań, które wpływają na sprawdzanie aktualności, takie jak If-None-Match i If-Modified-Since, wyświetlają się po prostu na podstawie interpretacji 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 automatycznie i bez dodatkowych działań będzie zajmować się buforowaniem 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 pozostanie taki sam i nie trzeba go ponownie pobierać.
  • Last-Modified. Ten nagłówek ma ten sam cel co ETag, ale do określenia, czy zasób uległ zmianie, używa strategii opartej na czasie, a nie strategii opartej na treści ETag.

Niektóre serwery WWW mają wbudowaną obsługę nagłówków domyślnych, a inne całkowicie pomijają nagłówki, o ile ich nie skonfigurujesz. Szczegóły dotyczące sposobu 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 ustalają, jaki rodzaj buforowania treści sprawdzi się najlepiej w przypadku danego typu treści. Prawdopodobnie zależy Ci na większej kontroli, dlatego poświęć 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 wersji adresów URL jest dobrym rozwiązaniem, ponieważ ułatwia unieważnienie odpowiedzi z pamięci podręcznej.

Załóżmy, że serwer nakazuje przeglądarkom buforowanie pliku 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 będzie 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 do wyczyszczenia pamięci podręcznej przeglądarki. W efekcie po utworzeniu 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 w pamięci podręcznej wcześniejszą (ale nadal ważną) wersję, używają starszej wersji odpowiedzi. Jak najlepiej wykorzystać oba te rozwiązania: buforowanie po stronie klienta i szybkie aktualizacje? Zmieniasz adres URL zasobu i wymuszasz na użytkownikach pobieranie nowej odpowiedzi po każdej zmianie treści. Zwykle robi się to, umieszczając odcisk cyfrowy pliku lub numer wersji w jego nazwie, na przykład 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 musi 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żesz dodać kroku kompilacji przed wdrożeniem aplikacji internetowej, więc nie da się dodać haszów do adresów URL zasobów. A każda aplikacja internetowa wymaga plików HTML – te pliki nigdy nie będą zawierać informacji o obsłudze wersji, ponieważ nikt nie będzie musiał korzystać z Twojej aplikacji internetowej, jeśli będzie musiał pamiętać, że URL, który mają odwiedzać, to https://example.com/index.34def12.html. Co więc możesz zrobić z tymi adresami URL?

To jeden ze scenariuszy, w których trzeba przyznać się do porażki. Samo buforowanie HTTP nie jest wystarczające, aby całkowicie ominąć sieć. (Nie martw się – wkrótce dowiesz się więcej o pracownikach usługowych, którzy dadzą Ci potrzebne wsparcie, by cofnąć bitwę na Twoją korzyść). Możesz jednak wykonać kilka czynności, które sprawią, że żądania sieciowe będą tak szybkie i efektywne, jak to tylko możliwe.

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

  • no-cache. To informuje przeglądarkę, że przed użyciem wersji adresu URL przechowywanej w pamięci podręcznej musi ona przeprowadzić ponowną weryfikację na serwerze.
  • no-store. Sprawia to, że przeglądarka i inne pośrednie pamięci podręczne (np. sieci CDN) nigdy nie przechowują żadnej wersji pliku.
  • private. Przeglądarki mogą zapisywać plik w pamięci podręcznej, ale pośrednie – nie.
  • public. Odpowiedź może być przechowywana w dowolnej pamięci podręcznej.

Zapoznaj się z załącznikiem: schemat blokowy Cache-Control, aby zwizualizować proces wybierania wartości atrybutu Cache-Control do użycia. Pamiętaj, że Cache-Control może akceptować listę dyrektyw rozdzielonych przecinkami. Zobacz Załącznik: Cache-Control przykłady.

Pomocne może być też ustawienie jednego z 2 dodatkowych nagłówków odpowiedzi: ETag lub Last-Modified. Jak wspomnieliśmy w nagłówkach odpowiedzi, funkcje ETag i Last-Modified służą do tego samego celu: wskazują, czy przeglądarka musi ponownie pobrać wygasły plik z pamięci podręcznej. Zalecana jest ETag, ponieważ jest ona dokładniejsza.

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 pobierać te same informacje, które znajdują się już w pamięci podręcznej. Właśnie ten problem ma rozwiązywać tokeny weryfikacyjne określone w nagłówku 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 odcisk cyfrowy jest generowany. Wystarczy, że prześle go 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 przesyłanie prośby o ponowną weryfikację. Spowoduje to aktywowanie nagłówków żądań If-Modified-Since lub If-None-Match, które zostały wspomniane 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 2 wartości się zgadzają, 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ługiwane we wszystkich przeglądarkach, a jego konfiguracja nie wymaga dużo pracy.

Warto zacząć od tych konfiguracji Cache-Control:

  • Cache-Control: no-cache w przypadku zasobów, które powinny być ponownie weryfikowane 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 też pomóc skuteczniej weryfikować wygasłe zasoby 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 inne sposoby optymalizacji wykorzystania pamięci podręcznej HTTP:

  • Używaj spójnych adresów URL. Jeśli udostępniasz tę samą treść pod różnymi adresami URL, będą one wielokrotnie pobierane i przechowywane.
  • Ogranicz 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 na oddzielny plik i zastosowanie krótkotrwałej strategii buforowania w przypadku często aktualizowanego kodu i strategii długiego czasu przechowywania w przypadku kodu, który rzadko się zmienia.
  • Jeśli zasady Cache-Control akceptowalne są w pewnym stopniu, zapoznaj się z nową dyrektywą stale-while-revalidate.

Dodatek: schemat blokowy typu Cache-Control

Schemat blokowy

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 1 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.