LW IT Solutions logo LW IT Solutions logo LW IT Solutions
« Przegląd bloga /Tworzenie stron internetowych/Tutorials / Cache-Control prosto wyjaśnione: co robią no-cache, no-store,...
Ten artykuł w innych językach:

Cache-Control prosto wyjaśnione: co robią no-cache, no-store, max-age i s-maxage

Cache-Control prosto wyjaśnione: co robią no-cache, no-store, max-age i s-maxage

Przejdź do interaktywnego przykładu ↓

Spis treści
  1. Dwie pamięci, nie jedna
  2. no-cache i no-store to nie dwa razy to samo słowo
  3. Dwie liczby dla dwóch pamięci
  4. Komu wolno w ogóle zapisywać
  5. Przeterminowane odpowiedzi wydawane celowo
  6. Co pokazuje jedna linijka nagłówka
  7. Pytania i odpowiedzi
  8. Źródła

Strona, która przy drugich odwiedzinach jest od razu, nie została pobrana ponownie. Wyszła z pamięci gdzieś między serwerem a ekranem, a pozwoliła na to jedna linijka nagłówka.

Ta linijka nazywa się Cache-Control. Jest krótka, składa się ze słów wyglądających na samo tłumaczące się, a dwa z nich znaczą niemal coś przeciwnego, choć brzmią jak synonimy.

Dwa pasma pamięci - przeglądarka i pamięci współdzielone - z regułami obowiązującymi każde z nich, a no-store poza obydwoma
Reguła stoi w paśmie, którego dotyczy. To, co stoi w obu, obowiązuje oba.

Dwie pamięci, nie jedna

Między serwerem a ekranem są zwykle dwa miejsca, w których odpowiedź może zostać.

Pierwszym jest przeglądarka na jednym urządzeniu. To, co tam leży, służy dokładnie jednej osobie i zostaje, dopóki nie wygaśnie albo nie zostanie usunięte.

Drugim jest pamięć współdzielona: CDN, firmowy pośrednik, cokolwiek stojącego po drodze i obsługującego wielu ludzi z jednej kopii. Jest skuteczniejsza z dwóch, bo jedna zapisana kopia oszczędza tysiące zapytań – i groźniejsza, bo strona osobista, która tam wyląduje, zostaje wydana niewłaściwym.

Niemal każde nieporozumienie wokół zapisywania bierze się z zapomnienia o drugiej pamięci. Reguły, które zdają się sobie przeczyć, zwykle zwracają się do różnych pamięci.

no-cache i no-store to nie dwa razy to samo słowo

Te dwa wyglądają jak para. Parą nie są.

no-store znaczy: niczego nie przechowywać. Żadnej kopii nigdzie, ani w przeglądarce, ani w pamięci współdzielonej, ani na dysku. Każde zapytanie wraca do serwera. To reguła dla wyciągu bankowego.

no-cache znaczy: przechowywać, ale przed użyciem zapytać. Kopia zostaje zapisana całkiem zwyczajnie; przeglądarce nie wolno jej tylko wydać bez sprawdzenia. Gdy serwer odpowie, że nic się nie zmieniło, zapisana kopia zostaje użyta i żadna treść nie płynie.

no-cache nie znaczy więc „nie zapisywać”. Znaczy „zapisywać, ale pytać za każdym razem” – i reguła ta istnieje właśnie po to, by zapisywanie stało się możliwe dla stron zmieniających się nieprzewidywalnie. Krótkie zapytanie kosztuje ułamek pełnego przesyłu.

Kto pisze no-store, a ma na myśli no-cache, oddaje tę oszczędność przy każdym pojedynczym zapytaniu. Kto pisze no-cache, a ma na myśli no-store, zostawia kopię czegoś poufnego na dysku.

Dwie liczby dla dwóch pamięci

max-age określa czas życia w sekundach. Dla pamięci współdzielonych można ustawić osobny czas za pomocą s-maxage, który ma tam pierwszeństwo przed max-age.

Strona główna Wikipedii pokazuje, po co są obie. Jej nagłówek brzmi s-maxage=86400, must-revalidate, max-age=3600: CDN może trzymać stronę cały dzień, przeglądarka godzinę. Kosztowna pamięć trzyma ją długo, osobista krótko – i jedna linijka reguluje oba.

Bez s-maxage pamięć współdzielona po prostu idzie za max-age. To przypadek zwyczajny i dlatego CDN trzyma czasem stronę o wiele dłużej albo krócej, niż zamierzano: nikt nie napisał dla niego osobnej liczby.

must-revalidate dopełnia obrazu. Gdy czas życia minie, zapisanej kopii nie wolno już użyć, nawet na chwilę, nawet przy nieosiągalnym serwerze. Bez tej reguły pamięć ma z wygasłą kopią pewien margines swobody.

Dwie półki bardzo różnej długości z tym samym rodzajem kafelków i pojedynczy koralowy kafelek leżący na ziemi pod obiema

Komu wolno w ogóle zapisywać

private i public nie opisują treści. Nazywają pamięć.

private znaczy: tylko przeglądarka jednej osoby. Pamięciom współdzielonym nie wolno tej odpowiedzi zatrzymać. To właściwe ustawienie dla wszystkiego, co pokazuje nazwisko, koszyk albo stan konta – dla wszystkiego złożonego pod pojedyncze odwiedziny.

public znaczy: pamięci współdzielone także mogą zatrzymać. Uchyla ponadto kilka reguł, które inaczej przemawiałyby przeciw zapisywaniu, i dlatego stoi też na stronach, które i tak dałyby się bez kłopotu zapisać.

Błąd jest tu cichy i poważny: strona osobista bez private, za CDN-em, zostaje raz zapisana i podana następnym odwiedzinom wraz z cudzym nazwiskiem. Nic się nie wywala, nic nie trafia do dziennika, a strona wygląda poprawnie – dla niewłaściwej osoby.

Przeterminowane odpowiedzi wydawane celowo

Dwa dodatki pozwalają pamięci wydać wygasłą kopię świadomie i oba sprawiają, że witryny wydają się szybsze, niż są.

stale-while-revalidate mówi: jeśli kopia właśnie wygasła, wydaj ją mimo to i pobierz w tle świeżą. Odwiedziny nie czekają na nic; następne dostaną nową wersję.

stale-if-error mówi: jeśli serwer jest nieosiągalny, wydawaj raczej starą kopię niż stronę błędu. Witryna z tą regułą przetrwa krótką awarię tak, że nikt tego nie zauważy.

Strona główna BBC używa obu, z wartościami 30 i 90 sekund. GitHub wysyła natomiast max-age=0, private, must-revalidate – nic nie zostaje wydane bez zapytania, bo strona repozytorium nie może być przeterminowana ani o sekundę.

Żadne z dwojga nie jest bardziej słuszne. To różne odpowiedzi na to samo pytanie: co jest tu gorsze, strona wolna czy stara.

Co pokazuje jedna linijka nagłówka

Linijka przychodzi z każdą odpowiedzią, a jej odczytanie kosztuje jedno zapytanie.

Warto zadać cztery pytania. Najpierw rozstrzygnij, czy potrzebne jest no-store, czy no-cache: bez przechowywania kopii czy z przechowywaniem i sprawdzaniem przed użyciem. Następnie sprawdź, czy spersonalizowana strona ma private i czy pamięć współdzielona ma osobne s-maxage, czy też jedna liczba określa oba czasy. Na koniec oceń, czy czas życia pasuje do częstotliwości zmian treści.

Sprawdzarka nagłówków bezpieczeństwa HTTP odczytuje nagłówki dowolnego adresu tak, jak czyta je przeglądarka, śledząc po drodze przekierowania.

Użyteczna odpowiedź to jedno zdanie: czy ta strona jest zapisywana tam, gdzie ma być, i tak długo, jak ma być – i przez nikogo więcej.

Pytania i odpowiedzi

Dlaczego no-cache oszczędza przesył tylko wtedy, gdy odpowiedź niesie ETag albo Last-Modified?

Ponieważ zapytanie sprawdzające potrzebuje wartości do porównania. Przeglądarka odsyła ją jako If-None-Match albo If-Modified-Since i dopiero wtedy serwer może odpowiedzieć kodem 304 Not Modified bez ponownego wysyłania treści. Bez żadnej z tych wartości nie ma czego porównać, a każde sprawdzenie staje się pełnym przesyłem.

Jak nieaktualna strona znika z CDN, który trzyma ją z s-maxage=86400?

Nie za sprawą nowego nagłówka. Kopie już zapisane niosą ze sobą swój czas życia; zmieniony nagłówek dotyczy dopiero następnej kopii. W CDN służy do tego wyczyszczenie pamięci przez panel administracyjny albo interfejs API, zwykle nazywane purge.

W przeglądarkach takiego środka nie ma. Kopia z max-age=3600 zostaje tam nawet godzinę, bez względu na to, co serwer w międzyczasie wysyła. Pasuje to do podziału w przykładzie Wikipedii: pamięć, którą operator może opróżnić, może trzymać stronę długo, a ta, do której nie sięga, tylko krótko.

Dla skryptów i arkuszy stylów zwykle stosuje się inną drogę: nowy adres dla każdej wersji, na przykład z numerem wersji albo sumą kontrolną w nazwie pliku, w połączeniu z długim czasem życia. Zmieniony plik ma wtedy nowy adres i żadna stara kopia nie stoi na przeszkodzie.

Jaką regułę uchyla public i kiedy robi się to ryzykowne?

Najważniejsza dotyczy żądań z nagłówkiem Authorization, na przykład za ochroną hasłem przez uwierzytelnianie HTTP. Według RFC 9111 pamięć współdzielona nie może zwykle użyć odpowiedzi na takie żądanie do obsługi kolejnych żądań, bo jest ona przeznaczona dla zalogowanej osoby. public wprost na to pozwala, podobnie jak s-maxage i must-revalidate.

Ryzykowne robi się to wtedy, gdy szablon ustawia public na wszystkich stronach, a obszar chroniony też temu podlega: CDN może wtedy zapisać odpowiedź i wydać ją odwiedzającym, którzy nigdy się nie zalogowali. Obszary chronione potrzebują w nagłówku private albo no-store, niezależnie od tego, co wysyła reszta witryny.

Czy stale-if-error działa także wtedy, gdy serwer odpowiada, ale błędem?

Tak. Według RFC 5861 za błąd uchodzą także kody stanu 500, 502, 503 i 504, a nie tylko nieosiągalny serwer. To, czy pamięć w ogóle respektuje tę regułę, zależy jednak od CDN i przeglądarki, a strony błędu wysłanej z kodem 200 żadna z nich nie rozpozna jako błędu.

Zrozum przez eksperyment

Kiedy przeglądarka musi zapytać ponownie?

Zmień wiek odpowiedzi. Następnie wybierz no-cache lub no-store.

Model odpowiedzi GET z ETag, którą można zapisać. Wiek zawiera czas przesyłania. Ten sam URL i Vary, bez innych dyrektyw i trybu offline.

Ten moduł działa w przeglądarce i nie wysyła ani nie zapisuje wpisanych danych.

Przejdź do odpowiedniego narzędzia →

Źródło ↗

Zrozum przez eksperyment

Jedna minuta: znajdziesz błąd?

Cache-Control: no-cache. Co może zrobić cache?

Przejdź do odpowiedniego narzędzia →

Źródło ↗

Lukas Wójcik

Lukas Wójcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Kontakt

Masz pytanie lub pomysł na projekt internetowy? Napisz krótko, o co chodzi. Formularz korzysta z reCAPTCHA do ochrony przed spamem.

Napisanie komentarza

Przypadki brzegowe pominięte w artykule i pytania o kod są tu mile widziane.

Adres e-mail nie jest publikowany. Pola obowiązkowe oznaczono gwiazdką.