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

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

  • Duże odpowiedzi wymagają wielu wymian między przeglądarką a serwerem.
  • Strona nie załaduje się, dopóki nie zostaną całkowicie pobrane wszystkie kluczowe zasoby.
  • Jeśli użytkownik korzysta z Twojej witryny z ograniczonym pakietem danych mobilnych, każde niepotrzebne żądanie sieciowe to strata pieniędzy.

Jak unikać zbędnych żądań sieciowych? Pamięć podręczna HTTP przeglądarki to pierwsza linia obrony. Nie jest to koniecznie najbardziej wydajne ani elastyczne podejście, a czas przechowywania odpowiedzi w pamięci podręcznej jest ograniczony, ale jest to skuteczne rozwiązanie, które jest obsługiwane we wszystkich przeglądarkach i nie wymaga wiele pracy.

Ten przewodnik zawiera podstawy skutecznego stosowania pamięci podręcznej HTTP.

Zgodność z przeglądarką

Nie ma jednego interfejsu API o nazwie HTTP Cache. Jest to ogólna nazwa kolekcji interfejsów API platformy internetowej. Te interfejsy API są obsługiwane we wszystkich przeglądarkach:

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

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 istnieje prawidłowa odpowiedź w pamięci podręcznej, która może być użyta do zrealizowania żądania. Jeśli występuje dopasowanie, odpowiedź jest odczytywana z pamięci podręcznej, co eliminuje opóźnienia w sieci i koszty przesyłania danych.

Działanie pamięci podręcznej HTTP jest kontrolowane przez kombinację nagłówków żądanianagłówków odpowiedzi. W idealnym scenariuszu masz kontrolę zarówno nad kodem aplikacji internetowej (który określa nagłówki żądania), jak i nad konfiguracją serwera WWW (która określa nagłówki odpowiedzi).

Aby uzyskać bardziej szczegółowe informacje, zapoznaj się z artykułem Pamięć podręczna HTTP na stronie MDN.

Nagłówki żądania: (zazwyczaj) używaj domyślnych ustawień

Istnieje kilka ważnych nagłówków, które powinny być uwzględnione w wychodzących żądaniach aplikacji internetowej, ale przeglądarka prawie zawsze ustawia je w Twoim imieniu, gdy wysyła żądania. Nagłówki żądania, które wpływają na sprawdzanie aktualności, takie jak If-None-MatchIf-Modified-Since, pojawiają się na podstawie interpretacji bieżących wartości w pamięci podręcznej HTTP przez przeglądarkę.

To dobra wiadomość – oznacza to, że nadal możesz umieszczać w pliku 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

Najważniejszym elementem konfiguracji buforowania HTTP są nagłówki, które serwer WWW dodaje do każdej wychodzącej odpowiedzi. Te nagłówki mają wpływ na skuteczne buforowanie:

  • Cache-Control. Serwer może zwrócić dyrektywę Cache-Control, aby określić, jak długo i w jaki sposób przeglądarka oraz inne pośrednie pamięci podręczne mają przechowywać poszczególne odpowiedzi.
  • ETag. Gdy przeglądarka znajdzie nieaktualną odpowiedź z pamięci podręcznej, może wysłać na serwer mały token (zwykle hasz zawartości pliku), aby sprawdzić, czy plik się zmienił. Jeśli serwer zwróci ten sam token, oznacza to, że plik jest taki sam i nie trzeba go ponownie pobierać.
  • Last-Modified. Ten nagłówek służy do tego samego celu co ETag, ale do określania, czy zasób się zmienił, używa strategii opartej na czasie, a nie strategii opartej na treści, jak w przypadku tagu ETag.

Niektóre serwery internetowe mają wbudowane wsparcie dla ustawiania tych nagłówków domyślnie, podczas gdy inne nie mają ich w ogóle, chyba że skonfigurujesz je ręcznie. Szczegóły dotyczące sposobów konfigurowania nagłówków różnią się w zależności od serwera WWW, którego używasz. Aby uzyskać dokładniejsze informacje, zapoznaj się z dokumentacją serwera.

Aby zaoszczędzić Ci czasu, podajemy instrukcje konfigurowania kilku popularnych serwerów WWW:

Pominięcie nagłówka odpowiedzi Cache-Control nie powoduje wyłączenia buforowania HTTP. Zamiast tego przeglądarki domyślają się, jaki typ zachowania w przypadku pamięci podręcznej jest najbardziej odpowiedni w przypadku danego typu treści. Prawdopodobnie chcesz mieć większą kontrolę niż oferuje to rozwiązanie, więc poświęć trochę czasu na skonfigurowanie nagłówków odpowiedzi.

Których wartości nagłówka odpowiedzi należy używać?

Podczas konfigurowania nagłówków odpowiedzi serwera WWW należy uwzględnić 2 ważne scenariusze.

Długie buforowanie adresów URL z wersjami

Załóżmy, że Twój serwer instruuje przeglądarki, aby przechowywały w pamięci podręcznej plik CSS przez 1 rok (Cache-Control: max-age=31536000), ale Twój projektant właśnie wprowadził awaryjną aktualizację, którą musisz natychmiast wdrożyć. Jak powiadomić przeglądarki, aby zaktualizowały „nieaktualną” kopię pliku w pamięci podręcznej? Nie możesz tego zrobić, chyba że zmienisz adres URL zasobu.

Gdy przeglądarka przechowuje odpowiedź w pamięci podręcznej, wersja z pamięci podręcznej jest używana do momentu, gdy nie jest już aktualna (zgodnie z ustawieniami max-age lub expires) albo do momentu, gdy zostanie usunięta z pamięci podręcznej z jakiegokolwiek innego powodu, np. gdy użytkownik ją usunie. 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 novej wersji, a użytkownicy, którzy wcześniej zapisali w pamięci podręcznej wcześniejszą (ale nadal ważną) kopię, korzystają ze starszej wersji odpowiedzi.

Jak połączyć zalety obu rozwiązań: buforowania po stronie klienta i szybkich aktualizacji? Zmieniasz adres URL zasobu i zmuszasz użytkownika do pobrania nowej odpowiedzi, gdy tylko zmieni się jej treść. Zwykle odbywa się to przez umieszczenie w nazwie pliku odcisku cyfrowego pliku lub numeru wersji, np. style.x234dff.css.

Odpowiadając na żądania dotyczące adresów URL, które zawierają „odcisk cyfrowy” lub informacje o wersjach i których zawartość nigdy nie powinna się zmieniać, dodaj Cache-Control: max-age=31536000 do swoich odpowiedzi.

Ustawienie tej wartości informuje przeglądarkę, że gdy będzie trzeba załadować ten sam adres URL w dowolnym momencie 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 żądania sieciowego do serwera WWW. Świetnie – dzięki temu od razu uzyskasz niezawodność i szybkość, które wynikają z unikania sieci.

Narzędzie do kompilacji, takie jak webpack, może zautomatyzować proces przypisywania odcisków palców haszowanych do adresów URL komponentów.

weryfikacja serwera w przypadku adresów URL bez wersji.

Niestety nie wszystkie wczytane przez Ciebie adresy URL są wersjonowane. Być może nie możesz uwzględnić etapu kompilacji przed wdrożeniem aplikacji internetowej, więc nie możesz dodawać haszy do adresów URL zasobów. Każda aplikacja internetowa potrzebuje plików HTML, które (prawie!) nigdy nie zawierają informacji o wersji, ponieważ nikt nie będzie chciał korzystać z aplikacji internetowej, jeśli będzie musiał pamiętać, że adres URL do odwiedzenia to https://example.com/index.34def12.html. Co możesz zrobić w przypadku tych adresów URL?

To jeden ze scenariuszy, w którym musisz uznać wyższość przeciwnika. Samo buforowanie HTTP nie jest wystarczająco skuteczne, aby całkowicie uniknąć sieci. (Nie martw się – wkrótce dowiesz się więcej o workerach usługowych, którzy zapewnią Ci wsparcie, dzięki któremu uda Ci się odwrócić losy bitwy.) Możesz jednak podjąć kilka działań, aby zapewnić jak najszybsze i skuteczne przesyłanie żądań do sieci.

Te wartości Cache-Control mogą pomóc Ci dostosować, gdzie i jak przechowywać w pamięci podręcznej adresy URL bez wersji:

  • no-cache. To informuje przeglądarkę, że przed użyciem wersji adresu URL z pamięci podręcznej musi ona za każdym razem ponownie sprawdzić poprawność danych na serwerze.
  • no-store. To powoduje, że przeglądarka i inne pośrednie pamięci podręczne (np. sieci CDN) nigdy nie przechowują żadnej wersji pliku.
  • private. Przeglądarki mogą zapisać 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 zobaczyć wizualizację procesu podejmowania decyzji, których wartości Cache-Control użyć, przejdź do Załącznika: schemat Cache-Control. Cache-Control może też przyjmować listę dyrektyw rozdzielonych przecinkami. Zobacz załącznik: przykłady Cache-Control.

Pomocne może być też ustawienie wartości ETag lub Last-Modified. Jak wspomniano w sekcji Nagłówki odpowiedzi, nagłówki ETagLast-Modified służą temu samemu celowi: określaniu, czy przeglądarka musi ponownie pobrać plik z pamięci podręcznej, którego ważność wygasła. Zalecamy użycie atrybutu ETag, ponieważ jest on dokładniejszy.

Załóżmy, że od momentu początkowego pobierania minęło 120 sekund i przeglądarka wysłała nowe żądanie tego samego zasobu. Najpierw przeglądarka sprawdza pamięć podręczną HTTP i odnajduje poprzednią odpowiedź. Niestety przeglądarka nie może użyć poprzedniej odpowiedzi, ponieważ jej czas ważności upłynął. 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 walidacyjne określone w nagłówku ETag. Serwer generuje i zwraca dowolny token, który jest zwykle haszem lub innym odciskiem palca zawartości pliku. Przeglądarka nie musi wiedzieć, jak generowany jest odcisk palca. Musi tylko wysłać go na serwer w następnym żądaniu. Jeśli odcisk palca jest taki sam, zasób się nie zmienił i przeglądarka może pominąć pobieranie.

Ustawienie wartości ETag lub Last-Modified znacznie zwiększa wydajność żądania ponownej walidacji, ponieważ pozwala wywołać nagłówki żądania If-Modified-Since lub If-None-Match wymienione w sekcji Nagłówki żądania.

Gdy prawidłowo skonfigurowany serwer WWW zobaczy te nagłówki przychodzących żądań, może sprawdzić, czy wersja zasobu, która jest już w przyborniku HTTP przeglądarki, jest zgodna z najnowszą wersją na serwerze WWW. Jeśli występuje dopasowanie, serwer może odpowiedzieć kodem HTTP 304 Not Modified, co jest równoznaczne z oświadczeniem „Używaj tego, co już masz”. Podczas wysyłania tego typu odpowiedzi trzeba przesłać bardzo mało danych, więc jest to zwykle znacznie szybsze niż wysyłanie kopii żądanego zasobu.

Wizualizacja klienta żądającego zasobu i serwera odpowiadającego nagłówkiem 304.
Przeglądarka wysyła do serwera żądanie /file i włącza nagłówek If-None-Match, aby poinformować serwer, że ma zwrócić pełny plik tylko wtedy, gdy ETag pliku na serwerze nie pasuje do wartości If-None-Match w przeglądarce. W tym przypadku obie wartości są zgodne, więc serwer zwraca odpowiedź 304 Not Modified z instrukcjami dotyczącymi tego, 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 poprawę wydajności wczytywania, ponieważ zmniejsza liczbę zbędnych żądań sieciowych. Jest obsługiwany we wszystkich przeglądarkach i nie wymaga zbyt wiele pracy przy konfiguracji.

Na początek możesz użyć tych konfiguracji Cache-Control:

  • Cache-Control: no-cache w przypadku zasobów, które przed każdym użyciem powinny zostać ponownie zweryfikowane przez serwer.
  • Cache-Control: no-store dla zasobów, które nigdy nie powinny być przechowywane w pamięci podręcznej.
  • Cache-Control: max-age=31536000 w przypadku zasobów z wersjami.

Nagłówek ETag lub Last-Modified może Ci pomóc w skuteczniejszym ponownym sprawdzaniu ważności wygasłych zasobów pamięci podręcznej.

Więcej informacji

Jeśli chcesz dowiedzieć się więcej o używaniu nagłówka Cache-Control, zapoznaj się ze sprawdzonymi metodami i uwagami dotyczącymi maksymalnego wieku danych w pamięci podręcznej autorstwa Jake'a Archibalda.

Wskazówki dotyczące optymalizacji wykorzystania pamięci podręcznej przez powracających użytkowników znajdziesz w artykule Miłość do pamięci podręcznej.

Załącznik: dodatkowe wskazówki

Jeśli masz więcej czasu, możesz zoptymalizować korzystanie z pamięci podręcznej HTTP w następujący sposób:

  • Używaj spójnych adresów URL. Jeśli udostępniasz te same treści pod różnymi adresami URL, będą one pobierane i przechowywane wielokrotnie.
  • Minimalizowanie odejść. Jeśli część zasobu (np. plik CSS) jest często aktualizowana, a pozostałości nie (np. kod biblioteki), rozważ podzielenie kodu, który jest często aktualizowany, na osobny plik i zastosowanie strategii krótkotrwałego przechowywania w pamięci podręcznej dla tego kodu oraz strategii długotrwałego przechowywania w pamięci podręcznej dla kodu, który nie zmienia się często.
  • Jeśli w Twoich zasadach Cache-Control dopuszczalny jest pewien stopień nieaktualności, zapoznaj się z nową dyrektywą stale-while-revalidate.

Dodatek: schemat blokowy Cache-Control

Schemat blokowy
Proces podejmowania decyzji dotyczących ustawiania 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 przez przeglądarki i pamięci pośrednie 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 przez przeglądarkę (ale nie przez pośrednie pamięci podręczne) przez maksymalnie 10 minut (60 sekund × 10 minut).
public, max-age=31536000 Odpowiedź może być przechowywana 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żdej prośbie.