Pobieranie zasobów przez sieć jest powolne i kosztowne:
- Duże odpowiedzi wymagają wielu cykli między przeglądarką a serwerem.
- Strona nie załaduje się, dopóki nie zostaną pobrane wszystkie jej zasoby krytyczne.
- Jeśli ktoś uzyskuje dostęp do Twojej witryny, korzystając z ograniczonego pakietu danych mobilnych, każde niepotrzebne żądanie sieciowe oznacza dla niego stratę pieniędzy.
Jak uniknąć niepotrzebnych żądań sieciowych? Pamięć podręczna HTTP przeglądarki to pierwsza linia obrony. Niekoniecznie jest to najbardziej wydajne i elastyczne podejście, a kontrola nad czasem przechowywania odpowiedzi w pamięci podręcznej jest ograniczona, ale jest to skuteczne, obsługiwane we wszystkich przeglądarkach i nie wymaga wiele pracy.
Ten przewodnik zawiera podstawowe informacje o skutecznym wdrażaniu buforowania 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
ETag
Last-Modified
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ź z pamięci podręcznej, której można użyć do realizacji żądania. Jeśli zostanie znalezione dopasowanie, odpowiedź jest odczytywana z pamięci podręcznej, co eliminuje zarówno opóźnienia sieci, jak i koszty danych związane z transferem.
Działanie pamięci podręcznej HTTP jest kontrolowane przez kombinację nagłówków żądań i nagłówków odpowiedzi. W idealnym przypadku masz kontrolę zarówno nad kodem aplikacji internetowej (który określa nagłówki żądań), jak i nad konfiguracją serwera WWW (która określa nagłówki odpowiedzi).
Więcej informacji znajdziesz w artykule MDN na temat buforowania HTTP.
Nagłówki żądań: zwykle najlepiej pozostawić ustawienia domyślne.
Istnieje wiele ważnych nagłówków, które powinny być uwzględniane w żądaniach wychodzących aplikacji internetowej, ale przeglądarka prawie zawsze dba o ich ustawienie w Twoim imieniu podczas wysyłania żądań. Nagłówki żądań, które wpływają na sprawdzanie aktualności, takie jak If-None-Match i If-Modified-Since, pojawiają się na podstawie interpretacji przez przeglądarkę bieżących wartości w pamięci podręcznej HTTP.
To dobra wiadomość – oznacza to, że możesz nadal umieszczać w kodzie HTML tagi takie jak <img src="my-image.png">, a przeglądarka automatycznie zajmie się buforowaniem HTTP bez dodatkowego wysiłku z Twojej strony.
Nagłówki odpowiedzi: konfigurowanie serwera WWW
Najważniejszą częścią konfiguracji buforowania HTTP są nagłówki, które serwer WWW dodaje do każdej odpowiedzi wychodzącej. Na efektywne działanie pamięci podręcznej wpływają te nagłówki:
Cache-Control. Serwer może zwrócić dyrektywęCache-Control, aby określić, jak i jak długo przeglądarka oraz inne pośrednie pamięci podręczne powinny przechowywać poszczególne odpowiedzi.ETag. Gdy przeglądarka znajdzie odpowiedź z pamięci podręcznej, która wygasła, może wysłać do serwera mały token (zwykle skrót 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 coETag, ale używa strategii opartej na czasie, aby określić, czy zasób uległ zmianie, w przeciwieństwie do strategii opartej na treści, którą stosujeETag.
Niektóre serwery WWW mają wbudowaną obsługę domyślnego ustawiania tych nagłówków, a inne całkowicie je pomijają, chyba że zostaną wyraźnie skonfigurowane. Szczegółowe informacje o sposobie konfigurowania nagłówków różnią się znacznie w zależności od używanego serwera WWW. Aby uzyskać najdokładniejsze informacje, zapoznaj się z dokumentacją serwera.
Aby ułatwić Ci zadanie, poniżej znajdziesz instrukcje konfigurowania kilku popularnych serwerów WWW:
Pominięcie nagłówka odpowiedzi Cache-Control nie wyłącza buforowania HTTP. Zamiast tego przeglądarki starają się odgadnąć, jaki sposób buforowania jest najbardziej odpowiedni dla danego typu treści. Prawdopodobnie chcesz mieć większą kontrolę, niż oferuje ta opcja, więc poświęć trochę czasu na skonfigurowanie nagłówków odpowiedzi.
Których wartości nagłówka odpowiedzi należy użyć?
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 serwer instruuje przeglądarki, aby przechowywały plik CSS w pamięci podręcznej przez rok (Cache-Control: max-age=31536000), ale projektant właśnie wprowadził pilną aktualizację, którą musisz natychmiast wdrożyć. Jak powiadomić przeglądarki, aby zaktualizowały „nieaktualną” kopię pliku w pamięci podręcznej? Nie, przynajmniej nie bez zmiany adresu URL zasobu.
Gdy 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, co jest określane przez max-age lub expires, lub dopóki nie zostanie usunięta z pamięci podręcznej z innego powodu, np. gdy użytkownik wyczyści pamięć podręczną przeglądarki. W efekcie różni użytkownicy mogą korzystać z różnych wersji pliku podczas tworzenia strony: użytkownicy, którzy właśnie pobrali zasób, używają nowej wersji, a użytkownicy, którzy zapisali w pamięci podręcznej wcześniejszą (ale nadal ważną) kopię, używają starszej wersji odpowiedzi.
Jak połączyć zalety obu rozwiązań: buforowania po stronie klienta i szybkich aktualizacji? Zmieniasz adres URL zasobu i wymuszasz na użytkowniku pobranie nowej odpowiedzi za każdym razem, gdy zmienia się jej zawartość. Zwykle robi się to przez umieszczenie odcisku cyfrowego pliku lub numeru wersji w nazwie pliku, np. style.x234dff.css.
Odpowiadając na żądania dotyczące adresów URL, które zawierają „odcisk cyfrowy” lub informacje o obsłudze wersji i których zawartość nigdy nie powinna się zmieniać, dodaj do odpowiedzi 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 najbliższego roku (31 536 000 sekund, czyli 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 zyskujesz niezawodność i szybkość, które wynikają z braku konieczności korzystania z sieci.
Narzędzia do kompilacji, takie jak webpack, mogą zautomatyzować proces przypisywania odcisków cyfrowych haszy do adresów URL komponentów.
Ponowna weryfikacja serwera w przypadku adresów URL bez wersji
Niestety nie wszystkie wczytywane adresy URL są wersjonowane. Być może nie możesz uwzględnić etapu kompilacji przed wdrożeniem aplikacji internetowej, więc nie możesz dodać haszy do adresów URL zasobów. Każda aplikacja internetowa potrzebuje plików HTML, które (prawie!) nigdy nie będą zawierać informacji o obsłudze wersji, ponieważ nikt nie będzie chciał korzystać z aplikacji internetowej, jeśli będzie musiał pamiętać, że adres URL, który należy odwiedzić, to https://example.com/index.34def12.html. Co możesz zrobić w przypadku tych adresów URL?
W takiej sytuacji musisz pogodzić się z porażką. Samo buforowanie HTTP nie wystarczy, aby całkowicie uniknąć sieci. (Nie martw się – wkrótce dowiesz się o skryptach service worker, które zapewnią wsparcie potrzebne do przechylenia szali zwycięstwa na Twoją stronę). Możesz jednak wykonać kilka czynności, aby żądania sieciowe były jak najszybsze i najbardziej wydajne.
Te wartości Cache-Control mogą pomóc Ci dostosować miejsce i sposób zapisywania w pamięci podręcznej adresów URL bez wersji:
no-cache. Informuje to przeglądarkę, że przed użyciem wersji adresu URL z pamięci podręcznej musi ona za każdym razem przeprowadzić ponowną weryfikację na serwerze.no-store. To polecenie instruuje przeglądarkę i inne pośrednie pamięci podręczne (np. CDN), aby nigdy nie przechowywały żadnej wersji pliku.private. Przeglądarki mogą zapisywać plik w pamięci podręcznej, ale pośrednie pamięci podręczne nie mogą tego robić.public. Odpowiedź może być przechowywana w dowolnej pamięci podręcznej.
Aby zobaczyć, jak przebiega proces decydowania, których wartości Cache-Control użyć, zapoznaj się z schematem blokowym w załączniku: Cache-Control. Cache-Control może też akceptować listę dyrektyw rozdzielonych przecinkami. Zobacz Dodatek: przykłady Cache-Control.
Pomocne może być też ustawienie ETag lub Last-Modified. Jak wspomniano w sekcji Nagłówki odpowiedzi, ETag i Last-Modified służą do tego samego celu: określenia, czy przeglądarka musi ponownie pobrać plik z pamięci podręcznej, który wygasł. Zalecamy używanie wartości ETag, ponieważ jest ona dokładniejsza.
Załóżmy, że od pierwszego pobrania minęło 120 sekund i 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ż jej ważność 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.
Ten problem rozwiązują tokeny weryfikacyjne określone w nagłówku ETag. Serwer generuje i zwraca dowolny token, który zwykle jest skrótem lub innym odciskiem cyfrowym zawartości pliku. Przeglądarka nie musi wiedzieć, jak odcisk cyfrowy jest generowany. 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 zwiększa wydajność żądania ponownej weryfikacji, ponieważ umożliwia wywołanie nagłówków żądania If-Modified-Since lub If-None-Match wymienionych w sekcji Nagłówki żądań.
Gdy prawidłowo skonfigurowany serwer WWW zobaczy te przychodzące nagłówki żądań, może sprawdzić, czy wersja zasobu, którą przeglądarka ma już w pamięci podręcznej HTTP, jest zgodna z najnowszą wersją na serwerze WWW. Jeśli tak, serwer może odpowiedzieć odpowiedzią HTTP 304 Not Modified, co oznacza „Hej, używaj dalej tego, co już masz”. Podczas wysyłania tego typu odpowiedzi przesyłanych jest bardzo mało danych, więc zwykle jest to znacznie szybsze niż wysyłanie kopii żądanego zasobu.
/file i dołącza nagłówek If-None-Match, aby poinstruować serwer, że ma zwrócić pełny plik tylko wtedy, gdy wartość ETag pliku na serwerze nie jest zgodna z wartością If-None-Match przeglądarki. W tym przypadku obie wartości są 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 poprawę wydajności wczytywania, ponieważ zmniejsza liczbę niepotrzebnych żądań sieciowych. Jest obsługiwany we wszystkich przeglądarkach i nie wymaga wiele pracy przy konfiguracji.
Te konfiguracje Cache-Control są dobrym punktem wyjścia:
Cache-Control: no-cachew przypadku zasobów, które powinny być ponownie sprawdzane na serwerze przed każdym użyciem.Cache-Control: no-storew przypadku zasobów, które nigdy nie powinny być przechowywane w pamięci podręcznej.Cache-Control: max-age=31536000w przypadku zasobów z wersjami.
Nagłówek ETag lub Last-Modified może pomóc w bardziej efektywnym ponownym sprawdzaniu ważności zasobów pamięci podręcznej, które wygasły.
Więcej informacji
Jeśli chcesz dowiedzieć się więcej o nagłówku Cache-Control, zapoznaj się z przewodnikiem Jake'a Archibalda Caching best practices and max-age gotchas (Sprawdzone metody buforowania i pułapki związane z dyrektywą max-age).
Wskazówki dotyczące optymalizacji wykorzystania pamięci podręcznej w przypadku powracających użytkowników znajdziesz w artykule Love your cache (w języku angielskim).
Załącznik: więcej wskazówek
Jeśli masz więcej czasu, oto dodatkowe sposoby na optymalizację 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, będą one pobierane i przechowywane wielokrotnie.
- Zminimalizuj liczbę rezygnacji. Jeśli część zasobu (np. plik CSS) jest często aktualizowana, a pozostała część pliku (np. kod biblioteki) nie, rozważ podzielenie często aktualizowanego kodu na osobny plik i zastosowanie strategii krótkiego przechowywania w pamięci podręcznej w przypadku często aktualizowanego kodu oraz strategii długiego przechowywania w pamięci podręcznej w przypadku kodu, który nie zmienia się często.
- Jeśli w Twoich zasadach
Cache-Controldopuszczalny jest pewien stopień nieaktualności, zapoznaj się z nową dyrektywąstale-while-revalidate.
Dodatek: schemat blokowy Cache-Control
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średnich pamięciach 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 pośrednich pamięciach podręcznych) 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 rok. |
no-store |
Odpowiedź nie może być zapisywana w pamięci podręcznej i musi być pobierana w całości przy każdym żądaniu. |