Twoja pamięć podręczna ❤️

Użytkownicy, którzy spróbują załadować Twoją witrynę po raz drugi, będą korzystać z pamięci podręcznej HTTP, więc dopilnuj, by działała prawidłowo.

Ten post jest uzupełnieniem filmu Love your cache, który był częścią rozszerzonego materiału na Chrome Dev Summit 2020. Obejrzyj ten film:

Gdy użytkownicy wczytują Twoją witrynę po raz drugi, ich przeglądarka będzie używać zasobów z pamięci podręcznej HTTP, aby przyspieszyć wczytywanie. Standardy dotyczące pamięci podręcznej w internecie pochodzą jednak z 1999 r. i są dość ogólnie zdefiniowane – ustalanie, czy plik, np. plik CSS lub obraz, może zostać pobrany ponownie z sieci, czy z pamięci podręcznej, nie jest dokładną nauką.

W tym poście omówię rozsądne, nowoczesne ustawienie domyślne buforowania, które w ogóle nie korzysta z buforowania. To jednak tylko ustawienie domyślne, które ma oczywiście więcej niuansów. Czytaj dalej.

Cele

Gdy witryna wczytuje się po raz 2, masz 2 cele:

  1. Zadbaj o to, aby użytkownicy otrzymali najnowszą dostępną wersję. Wprowadzane przez Ciebie zmiany powinny być szybko widoczne.
  2. Wykonaj czynność 1, pobierając jak najmniejsze dane z sieci.

Ogólnie rzecz biorąc, przy ponownym wczytywaniu witryny klientom lepiej jest przesyłać tylko najmniejszą zmianę. Ustrukturyzowanie witryny w sposób zapewniający najbardziej wydajną dystrybucję każdej zmiany jest trudne (więcej informacji na ten temat znajdziesz poniżej i w filmie).

Podczas korzystania z pamięci podręcznej należy też zwracać uwagę na inne kwestie. Możesz na przykład zdecydować, że pamięć podręczna HTTP przeglądarki użytkownika będzie przechowywać dane z Twojej witryny przez długi czas, aby nie trzeba było wysyłać żadnych żądań sieciowych. Możesz też mieć skrypt service worker, który będzie obsługiwać witrynę całkowicie offline, zanim sprawdzi, czy jest aktualny. Jest to opcja ekstremalna, która jest odpowiednia i używana w przypadku wielu aplikacji offline, ale internet nie musi być ograniczony tylko do pamięci podręcznej ani nawet do sieci.

Tło

Jako programiści stron internetowych jesteśmy przyzwyczajeni do koncepcji „nieaktualnej pamięci podręcznej”. Jednak prawie instynktownie znamy dostępne narzędzia, które mogą rozwiązać ten problem: „twarde odświeżenie”, otwarcie okna incognito lub użycie kombinacji narzędzi programistycznych przeglądarki w celu wyczyszczenia danych witryny.

Zwykli użytkownicy internetu nie mają tego luksusu. Chociaż naszym głównym celem jest zapewnienie użytkownikom świetnej zabawy podczas korzystania z drugiego poziomu ładowania, ważne jest też, aby nie tracili czasu ani nie utknęli. Obejrzyj film, jeśli chcesz dowiedzieć się, jak prawie udało nam się utknąć w witrynie web.dev/live.

Oto kilka informacji ogólnych: bardzo częstą przyczyną „nieaktualnej pamięci podręcznej” jest domyślne używanie pamięci podręcznej z 1999 r. Opiera się na nagłówku Last-Modified:

Diagram pokazujący, jak długo różne zasoby są przechowywane w pamięci podręcznej przez przeglądarkę użytkownika
Komponenty wygenerowane w różnych momentach (w kolorze szarym) są przechowywane w pamięci podręcznej przez różne czasy, więc przy drugim wczytaniu może zostać uwzględniona kombinacja nowych zasobów z pamięci podręcznej i nowych.

Każdy wczytany plik jest przechowywany przez dodatkowe 10% swojego bieżącego czasu przechowywania (w takiej postaci, w jakiej widzi go przeglądarka). Jeśli na przykład index.html zostało utworzone miesiąc temu, będzie przechowywane w pamięci podręcznej przeglądarki przez około 3 dni.

W przeszłości była to chęć okazania dobrej woli, ale biorąc pod uwagę ścisłą integrację współczesnych witryn, takie domyślne zachowanie może spowodować, że użytkownik będzie miał pliki przeznaczone do różnych wersji Twojej witryny (np. plik JS z wersji z wtorku i plik CSS z wersji z piątku), ponieważ te pliki nie zostały zaktualizowane dokładnie w tym samym czasie.

Dobrze oświetlona ścieżka

Obecnie domyślnym ustawieniem pamięci podręcznej jest brak korzystania z niej i używanie CDN do dostarczania treści użytkownikom. Po każdym wczytaniu witryny użytkownik sprawdza w sieci, czy jest aktualna. To żądanie będzie miało krótki czas oczekiwania, ponieważ będzie dostarczane przez sieć CDN geograficznie blisko każdego użytkownika.

Możesz skonfigurować hosta internetowego, aby odpowiadał na żądania internetowe za pomocą tego nagłówka:

Cache-Control: max-age=0,must-revalidate,public

Oznacza to, że plik jest ważny przez nieokreślony czas i należy go zweryfikować w sieci, zanim będzie można go ponownie użyć (w przeciwnym razie jest on tylko „zalecany”).

Ten proces weryfikacji jest stosunkowo tani pod względem przesyłanych bajtów – jeśli duży plik obrazu się nie zmienił, przeglądarka otrzyma małą odpowiedź 304, ale kosztem opóźnienia, ponieważ użytkownik musi się jeszcze połączyć z siecią, aby się tego dowiedzieć. To jest główny minus tej metody. Może ono działać bardzo dobrze w przypadku osób korzystających z szybkich połączeń w krajach rozwiniętych, w których wybrany przez Ciebie CDN ma świetne pokrycie, ale nie będzie działać dobrze w przypadku osób korzystających z wolniejszych połączeń komórkowych lub z niedostatecznej infrastruktury.

Niezależnie od tego, jest to nowoczesne podejście, które jest domyślnie używane w popularnej sieci CDN Netlify, ale można je skonfigurować w prawie każdej sieci CDN. W przypadku Hostingu Firebase możesz umieścić ten nagłówek w sekcji hostingu w pliku firebase.json:

"headers": [
  // Be sure to put this last, to not override other headers
  {
    "source": "**",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=0,must-revalidate,public"
    }
  }
]

Nadal uważam, że to rozsądne ustawienie domyślne, ale to tylko ustawienie domyślne. Czytaj dalej, aby dowiedzieć się, jak wprowadzić zmiany domyślne.

Adresy URL z odciskiem cyfrowym

Uwzględniając hasz treści pliku w nazwie zasobów, obrazów itp. wyświetlanych w witrynie, zyskujesz pewność, że pliki te zawsze będą zawierały niepowtarzalną treść – w efekcie zostaną utworzone pliki o nazwie sitecode.af12de.js. Gdy Twój serwer odpowiada na żądania tych plików, możesz bezpiecznie poinstruować przeglądarki użytkowników, aby buforowały je przez dłuższy czas, konfigurując je za pomocą tego nagłówka:

Cache-Control: max-age=31536000,immutable

Ta wartość to rok w sekundach. Zgodnie ze specyfikacją oznacza to „na zawsze”.

Nie generuj tych haszy ręcznie – to zbyt dużo pracy ręcznej. W tym celu możesz użyć narzędzi takich jak Webpack, Rollup itp. Więcej informacji znajdziesz w raporcie dotyczącym narzędzi.

Pamiętaj, że w przypadku adresów URL z odciskami cyfrowymi nie tylko JavaScript może być korzystny – zasoby takie jak ikony, CSS i inne stałe pliki danych również mogą być nazywane w ten sposób. (Pamiętaj, aby obejrzeć film powyżej, aby dowiedzieć się więcej o podziale kodu, który pozwala zmniejszyć ilość kodu wysyłanego przy każdej zmianie w witrynie).

Niezależnie od tego, jak Twoja witryna radzi sobie z buforowaniem, tego typu pliki z odciskami palców są niezwykle cenne dla każdej witryny, którą tworzysz. Większość witryn nie jest aktualizowana przy każdej wersji.

Oczywiście nie możemy w ten sposób zmienić nazwy „przyjaznych” stron dla użytkowników: zmieniając nazwę pliku index.html na index.abcd12.html. Takich „przyjaznych” adresów URL nie można zmieniać ani zapisywać w pamięci podręcznej, co prowadzi do sytuacji, w której możemy znaleźć złoty środek.

Środek

W przypadku pamięci podręcznej jest oczywiście miejsce na kompromis. Przedstawiłem 2 skrajne opcje: nigdyzawsze. Będzie też kilka plików, które warto przechowywać w pamięci podręcznej przez jakiś czas, np. wspomniane powyżej „przyjazne” adresy URL.

Jeśli chcesz przechowywać w pamięci podręcznej te „przyjazne” adresy URL i ich kod HTML, warto sprawdzić, jakie zależności zawierają, jak mogą być przechowywane w pamięci podręcznej oraz jak przechowywanie w pamięci podręcznej ich adresów URL może na Ciebie wpłynąć. Przyjrzyjmy się stronie HTML, która zawiera taki obraz:

<img src="/images/foo.jpeg" loading="lazy" />

Jeśli zaktualizujesz lub zmienisz witrynę, usuwając lub zmieniając ten wolnowczytywany obraz, użytkownicy wyświetlający kod HTML zapisany w pamięci podręcznej mogą zobaczyć nieprawidłowy lub brakujący obraz, ponieważ oryginalny /images/foo.jpeg nadal jest zapisany w pamięci podręcznej podczas kolejnych wizyt w Twojej witrynie.

Jeśli zachowasz ostrożność, nie powinno to mieć wpływu na Twoje konto. Należy jednak pamiętać, że gdy Twoja witryna jest przechowywana w pamięci podręcznej przez użytkowników, nie istnieje już tylko na Twoich serwerach. Zamiast tego mogą one występować w elementach w pamięci podręcznej przeglądarek użytkowników.

Większość przewodników dotyczących pamięci podręcznej zawiera informacje o tym rodzaju ustawieniach – czy chcesz przechowywać dane w pamięci podręcznej przez godzinę, kilka godzin itd. Aby skonfigurować tego rodzaju buforowanie, użyj nagłówka podobnego do tego (który jest przechowywany w pamięci podręcznej przez 3600 sekund, czyli 1 godzinę):

Cache-Control: max-age=3600,immutable,public

Jeszcze jedna uwaga. Jeśli tworzysz treści aktualne, które zwykle są dostępne dla użytkowników tylko raz (np. artykuły informacyjne), nie powinny one być przechowywane w pamięci podręcznej. Użyj więc domyślnych ustawień. Często przeszacowujemy wartość buforowania w porównaniu z chęcią użytkownika, aby zawsze widzieć najnowsze i najlepsze treści, takie jak istotna aktualizacja wiadomości lub bieżącego wydarzenia.

Opcje inne niż HTML

Oprócz HTML, inne opcje plików z poziomu pośredniego to:

  • Ogólnie szukaj zasobów, które nie wpływają na inne

    • Na przykład: unikaj CSS, bo powoduje on zmiany w sposobie renderowania kodu HTML
  • duże obrazy używane w ramach aktualnych artykułów;

    • Użytkownicy prawdopodobnie nie będą czytać danego artykułu więcej niż kilka razy, więc nie przechowuj zdjęć ani obrazów nagłówka w pamięci podręcznej na zawsze, ponieważ zajmie to zbyt dużo miejsca na dane.
  • Zasób, który reprezentuje coś, co samo ma czas trwania

    • Dane JSON o pogodzie mogą być publikowane tylko co godzinę, więc możesz przechowywać w pamięci podręcznej poprzedni wynik przez godzinę – nie zmieni się on w Twoim oknie
    • Kompilacje projektu open source mogą być ograniczone pod względem szybkości, dlatego należy przechowywać w pamięci podręcznej obraz stanu kompilacji do momentu, gdy stan może się zmienić.

Podsumowanie

Gdy użytkownicy wczytują Twoją witrynę po raz drugi, oznacza to, że już Ci zaufali i chcą wrócić, aby skorzystać z Twojej oferty. Obecnie nie chodzi tylko o skrócenie czasu ładowania. Masz do dyspozycji wiele opcji, dzięki którym przeglądarka wykona tylko te zadania, które są niezbędne do szybkiego i aktualnego działania przeglądarki.

Buforowanie nie jest nową koncepcją w internecie, ale być może potrzebujesz sensownego domyślnego ustawienia. Zastanów się, czy nie warto użyć takiego ustawienia i włączyć lepsze strategie buforowania, gdy będziesz ich potrzebować. Dziękujemy za uwagę!

Zobacz też

Ogólny przewodnik dotyczący pamięci podręcznej HTTP znajdziesz w artykule Zapobieganie zbędnym żądaniom sieciowym dzięki pamięci podręcznej HTTP.