Pamięć podręczna to potężne narzędzie. Dzięki temu aplikacje są mniej zależne od warunków sieciowych. Dzięki dobremu wykorzystaniu pamięci podręcznej możesz udostępnić aplikację internetową w trybie offline i wyświetlać zasoby tak szybko, jak to możliwe, w dowolnych warunkach sieciowych. Jak wspomnieliśmy w sekcji Komponenty i dane, możesz wybrać najlepszą strategię buforowania niezbędnych komponentów. Aby zarządzać pamięcią podręczną, service worker korzysta z interfejsu Cache Storage API.
Interfejs Cache Storage API jest dostępny w różnych kontekstach:
- kontekst okna (główny wątek aplikacji PWA);
- Skrypt service worker.
- wszelkie inne instancje robocze, z których korzystasz.
Zaletą zarządzania pamięcią podręczną za pomocą service workerów jest to, że ich cykl życia nie jest powiązany z oknem, co oznacza, że nie blokujesz wątku głównego. Pamiętaj, że aby korzystać z interfejsu Cache Storage API, większość tych kontekstów musi być objęta połączeniem TLS.
Co zapisywać w pamięci podręcznej
Pierwsze pytanie, jakie możesz sobie zadać w związku z pamięcią podręczną, to co należy w niej przechowywać. Nie ma na to jednej odpowiedzi, ale możesz zacząć od wszystkich minimalnych zasobów potrzebnych do renderowania interfejsu.
Powinny one obejmować:
- Główny plik HTML (start_url aplikacji).
- Arkusz stylów CSS potrzebny do głównego interfejsu.
- Obrazy używane w interfejsie.
- Pliki JavaScript wymagane do renderowania interfejsu.
- Dane, np. plik JSON, wymagane do wyświetlenia podstawowej wersji.
- czcionki internetowe,
- W aplikacji wielostronicowej inne dokumenty HTML, które chcesz szybko wyświetlać lub udostępniać w trybie offline.
Możliwość korzystania w trybie offline
Możliwość działania w trybie offline jest jednym z wymagań dotyczących progresywnych aplikacji internetowych, ale nie każda PWA musi zapewniać pełną funkcjonalność w trybie offline. Dotyczy to np. rozwiązań do gier w chmurze czy aplikacji do obsługi kryptowalut. Dlatego możesz zaoferować podstawowy interfejs użytkownika, który poprowadzi użytkowników przez te sytuacje.
Progresywna aplikacja internetowa nie powinna renderować komunikatu o błędzie przeglądarki informującego, że silnik renderowania nie może wczytać strony. Zamiast tego użyj service workera, aby wyświetlać własne komunikaty, unikając ogólnego i mylącego błędu przeglądarki.
W zależności od potrzeb progresywnej aplikacji internetowej możesz zastosować różne strategie buforowania. Dlatego ważne jest, aby zaprojektować wykorzystanie pamięci podręcznej w taki sposób, aby zapewnić szybkie i niezawodne działanie. Jeśli na przykład wszystkie zasoby aplikacji pobierają się szybko, nie zajmują dużo miejsca i nie wymagają aktualizacji przy każdym żądaniu, buforowanie wszystkich zasobów będzie dobrą strategią. Jeśli jednak masz zasoby, które muszą być w najnowszej wersji, możesz w ogóle nie zapisywać ich w pamięci podręcznej.
Korzystanie z interfejsu API
Użyj interfejsu Cache Storage API, aby zdefiniować w swojej domenie zestaw pamięci podręcznych, z których każda jest identyfikowana za pomocą zdefiniowanej przez Ciebie nazwy w postaci ciągu znaków. Dostęp do interfejsu API uzyskuje się za pomocą obiektu caches
, a metoda open
umożliwia tworzenie lub otwieranie utworzonej już pamięci podręcznej. Metoda open zwraca obietnicę dotyczącą obiektu pamięci podręcznej.
caches.open("pwa-assets")
.then(cache => {
// you can download and store, delete or update resources with cache arguments
});
Pobieranie i przechowywanie komponentów
Aby poprosić przeglądarkę o pobranie i przechowywanie zasobów, użyj metod add
lub addAll
. Metoda add
wysyła żądanie i przechowuje jedną odpowiedź HTTP, a metoda addAll
– grupę odpowiedzi HTTP jako transakcję na podstawie tablicy żądań lub adresów URL.
caches.open("pwa-assets")
.then(cache => {
cache.add("styles.css"); // it stores only one resource
cache.addAll(["styles.css", "app.js"]); // it stores two resources
});
Interfejs pamięci podręcznej przechowuje całą odpowiedź, w tym wszystkie nagłówki i treść. Dzięki temu możesz później pobrać go za pomocą żądania HTTP lub adresu URL jako klucza. Więcej informacji znajdziesz w rozdziale dotyczącym wyświetlania.
Kiedy zapisywać w pamięci podręcznej
W przypadku PWA to Ty decydujesz, kiedy zapisywać pliki w pamięci podręcznej. Jednym ze sposobów jest przechowywanie jak największej liczby zasobów podczas instalowania procesu roboczego usługi, ale zwykle nie jest to najlepsze rozwiązanie. Buforowanie niepotrzebnych zasobów marnuje przepustowość i miejsce na dane oraz może spowodować, że aplikacja będzie udostępniać nieaktualne zasoby.
Nie musisz buforować wszystkich zasobów naraz. Możesz to robić wielokrotnie w trakcie cyklu życia progresywnej aplikacji internetowej, np.:
- Podczas instalacji service workera.
- Po pierwszym wczytaniu strony.
- Gdy użytkownik przejdzie do sekcji lub trasy.
- Gdy sieć jest nieaktywna.
Możesz poprosić o pobranie nowych plików do pamięci podręcznej w wątku głównym lub w kontekście service workera.
Buforowanie zasobów w usłudze Service Worker
Jednym z najczęstszych scenariuszy jest buforowanie minimalnego zestawu zasobów podczas instalowania procesu roboczego usługi. Aby to zrobić, możesz użyć interfejsu pamięci podręcznej w zdarzeniu install
w usłudze Service Worker.
Wątek procesu roboczego usługi można w każdej chwili zatrzymać, dlatego możesz poprosić przeglądarkę o zaczekanie na zakończenie działania obietnicy addAll
, aby zwiększyć szansę na zapisanie wszystkich zasobów i zapewnić spójność aplikacji. Przykład poniżej pokazuje, jak to zrobić za pomocą metody waitUntil
argumentu zdarzenia otrzymanego w odbiorniku zdarzeń service workera.
const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", event => {
event.waitUntil(
caches.open("pwa-assets")
.then(cache => {
return cache.addAll(urlsToCache);
});
);
});
waitUntil()
Metoda otrzymuje obietnicę i prosi przeglądarkę o poczekanie, aż zadanie w obietnicy zostanie rozwiązane (spełnione lub nie), zanim zakończy proces roboczy usługi. Może być konieczne połączenie obietnic i zwrócenie wywołań add()
lub addAll()
, aby pojedynczy wynik trafił do metody waitUntil()
.
Obietnice możesz też obsługiwać za pomocą składni async/await. W takim przypadku musisz utworzyć funkcję asynchroniczną, która może wywoływać await
i zwracać obietnicę do waitUntil()
po wywołaniu, jak w tym przykładzie:
const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", (event) => {
let cacheUrls = async () => {
const cache = await caches.open("pwa-assets");
return cache.addAll(urlsToCache);
};
event.waitUntil(cacheUrls());
});
Żądania dotyczące różnych domen i nieprzejrzyste odpowiedzi
Twoja progresywna aplikacja internetowa może pobierać i buforować zasoby z Twojej domeny i domen zewnętrznych, np. treści z sieci CDN innych firm. W przypadku aplikacji obejmującej wiele domen interakcja z pamięcią podręczną jest bardzo podobna do żądań dotyczących tego samego pochodzenia. Żądanie jest wykonywane, a kopia odpowiedzi jest przechowywana w pamięci podręcznej. Podobnie jak w przypadku innych zasobów zapisanych w pamięci podręcznej, można go używać tylko w domenie aplikacji.
Zasób zostanie zapisany jako nieprzezroczysta odpowiedź, co oznacza, że Twój kod nie będzie mógł wyświetlać ani modyfikować zawartości ani nagłówków tej odpowiedzi. Nieprzezroczyste odpowiedzi nie ujawniają też swojego rzeczywistego rozmiaru w interfejsie API pamięci, co wpływa na limity. Niektóre przeglądarki podają duże rozmiary, np. 7 MB, niezależnie od tego, czy plik ma tylko 1 KB.
Aktualizowanie i usuwanie komponentów
Komponenty możesz aktualizować za pomocą ikony cache.put(request, response)
, a usuwać za pomocą ikony delete(request)
.
Więcej informacji znajdziesz w dokumentacji obiektu Cache.
Debugowanie pamięci podręcznej
Wiele przeglądarek umożliwia debugowanie zawartości pamięci podręcznej na karcie Aplikacja w Narzędziach deweloperskich. Możesz tam zobaczyć zawartość każdej pamięci podręcznej w bieżącym źródle. Więcej informacji o tych narzędziach znajdziesz w rozdziale Narzędzia i debugowanie.