Do tej pory pojawiały się tylko wzmianki i małe fragmenty kodu
interfejsu Cache
.
Aby efektywnie używać mechanizmów Service Worker, musisz zastosować co najmniej 1 strategię buforowania
co wymaga znajomości interfejsu Cache
.
Strategia buforowania to interakcja między zdarzeniem fetch
skryptu service worker a interfejsem Cache
.
Sposób zapisywania strategii buforowania zależy od tego,
na przykład lepiej obsługiwać żądania zasobów statycznych inaczej niż dokumenty,
co wpływa na sposób tworzenia strategii buforowania.
Zanim przejdziemy do omówienia strategii,
porozmawiajmy przez chwilę o tym, czym nie jest interfejs Cache
,
oraz krótkie podsumowanie niektórych dostępnych metod zarządzania pamięciami podręcznymi instancji service worker.
Interfejs Cache
a pamięć podręczna HTTP
Jeśli nie znasz jeszcze interfejsu Cache
,
to może wydawać się kuszące,
lub przynajmniej związane z pamięcią podręczną HTTP. To nieprawda.
- Interfejs
Cache
jest mechanizmem buforowania całkowicie niezależnym od pamięci podręcznej HTTP. - Cokolwiek innego
Cache-Control
używana przez Ciebie do wpływu na pamięć podręczną HTTP nie ma wpływu na to, jakie zasoby są zapisywane w interfejsieCache
.
Pomyśl o pamięci podręcznej przeglądarki jako warstwowej. Pamięć podręczna HTTP to niskopoziomowa pamięć podręczna napędzana parami klucz-wartość z dyrektywami wyrażonymi w nagłówkach HTTP.
Interfejs Cache
to natomiast pamięć podręczna wysokiego poziomu obsługiwana przez interfejs API JavaScript.
Zapewnia to większą elastyczność niż w przypadku stosunkowo uproszczonych par klucz-wartość HTTP.
co pozwala korzystać ze strategii buforowania.
Oto kilka ważnych metod interfejsu API związanych z pamięciami podręcznymi skryptu service worker:
CacheStorage.open
aby utworzyć nową instancjęCache
.Cache.add
iCache.put
do przechowywania odpowiedzi sieci w pamięci podręcznej mechanizmu Service Worker.Cache.match
aby znaleźć odpowiedź z pamięci podręcznej w instancjiCache
.Cache.delete
, aby usunąć odpowiedź z pamięci podręcznej z instancjiCache
.
Oto niektóre spośród nich. Istnieją inne przydatne metody, ale to tylko podstawowe funkcje, które omówimy w dalszej części tego przewodnika.
Skromne wydarzenie fetch
Drugą połową strategii buforowania jest kod mechanizmu Service Worker
fetch
.
Do tej pory w tej dokumentacji słyszeliśmy o „przechwytywaniu żądań sieciowych”,
a w zdarzeniu fetch
w skrypcie service worker
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('install', (event) => {
event.waitUntil(caches.open(cacheName));
});
self.addEventListener('fetch', async (event) => {
// Is this a request for an image?
if (event.request.destination === 'image') {
// Open the cache
event.respondWith(caches.open(cacheName).then((cache) => {
// Respond with the image from the cache or from the network
return cache.match(event.request).then((cachedResponse) => {
return cachedResponse || fetch(event.request.url).then((fetchedResponse) => {
// Add the network response to the cache for future visits.
// Note: we need to make a copy of the response to save it in
// the cache and use the original as the request response.
cache.put(event.request, fetchedResponse.clone());
// Return the network response
return fetchedResponse;
});
});
}));
} else {
return;
}
});
To jest przykład zabawki – którym można przekonać się, jak działa to w praktyce. które pokazują, co potrafią specjaliści ds. usług. Powyższy kod wykonuje następujące operacje:
- Sprawdź właściwość
destination
żądania, by zobaczyć, czy to żądanie obrazu. - Jeśli obraz znajduje się w pamięci podręcznej skryptu service worker, udostępniaj go stamtąd. Jeśli nie, pobierz obraz z sieci. zapisać odpowiedź w pamięci podręcznej i zwrócić odpowiedź sieciową.
- Wszystkie inne żądania są przekazywane przez mechanizm Service Worker bez interakcji z pamięcią podręczną.
Obiekt event
pobierania zawiera element
request
usługa
Znajdziesz tam informacje, które pomogą Ci zidentyfikować typ każdego żądania:
url
czyli adres URL żądania sieciowego obsługiwanego obecnie przez zdarzeniefetch
.method
która jest metodą żądania (np.GET
lubPOST
).mode
z opisem trybu żądania. Wartość'navigate'
jest często używana do odróżniania żądań dokumentów HTML od innych żądań.destination
który opisuje typ żądanych treści w sposób umożliwiający uniknięcie użycia rozszerzenia pliku żądanego zasobu.
I teraz to asynchronizacja to nazwa gry.
Na pewno pamiętasz, że zdarzenie install
oferuje:
event.waitUntil
.
która przyjmuje obietnicę, i czeka na rozwiązanie problemu, zanim przejdziesz do aktywacji.
Zdarzenie fetch
ma podobne
Metoda event.respondWith
których można użyć do zwrócenia wyniku funkcji asynchronicznego
fetch
prośba
lub odpowiedź zwrócona przez interfejs Cache
match
.
Strategie buforowania
Teraz już wiesz, jak działają instancje Cache
i moduł obsługi zdarzeń fetch
.
czas na zapoznanie się ze strategiami buforowania skryptu service worker.
Chociaż możliwości są praktycznie nieograniczone,
bazują na strategiach dostarczanych z Workbox,
dzięki czemu zorientować się, co dzieje się w wewnętrznej aplikacji Workbox.
Tylko pamięć podręczna
Zaczniemy od prostej strategii buforowania, którą będziemy nazywać „Tylko pamięć podręczna”. Chodzi o to, że gdy skrypt service worker kontroluje stronę, pasujące żądania będą zawsze trafiać do pamięci podręcznej. Oznacza to, że zasoby w pamięci podręcznej muszą być wstępnie zapisane w pamięci podręcznej, aby wzorzec mógł działać. i że zasoby te nie będą aktualizowane w pamięci podręcznej, dopóki skrypt service worker nie zostanie zaktualizowany.
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
// Assets to precache
const precachedAssets = [
'/possum1.jpg',
'/possum2.jpg',
'/possum3.jpg',
'/possum4.jpg'
];
self.addEventListener('install', (event) => {
// Precache assets on install
event.waitUntil(caches.open(cacheName).then((cache) => {
return cache.addAll(precachedAssets);
}));
});
self.addEventListener('fetch', (event) => {
// Is this one of our precached assets?
const url = new URL(event.request.url);
const isPrecachedRequest = precachedAssets.includes(url.pathname);
if (isPrecachedRequest) {
// Grab the precached asset from the cache
event.respondWith(caches.open(cacheName).then((cache) => {
return cache.match(event.request.url);
}));
} else {
// Go to the network
return;
}
});
Powyżej tablica zasobów jest wstępnie buforowana podczas instalacji.
Gdy skrypt service worker obsługuje pobieranie,
sprawdzamy, czy adres URL żądania obsługiwany przez zdarzenie fetch
znajduje się w tablicy zasobów wstępnie zapisanych w pamięci podręcznej.
Jeśli tak jest, pobieramy zasób z pamięci podręcznej i pomijamy sieć.
Pozostałe żądania przechodzą do sieci,
i tylko w sieci.
Aby zobaczyć, jak działa ta strategia,
wypróbuj tę wersję demonstracyjną przy otwartej konsoli.
Tylko sieć
Przeciwieństwo opcji „Tylko pamięć podręczna” to „Tylko sieć”, gdy żądanie jest przekazywane przez skrypt service worker do sieci bez interakcji z pamięcią podręczną skryptu service worker. To dobry sposób na zapewnienie aktualności treści (np. za pomocą znaczników). ale w ogóle nie będzie działać, gdy użytkownik będzie offline.
Zapewnienie, że żądanie zostanie przekazane do sieci, wystarczy, że nie wywołasz usługi event.respondWith
w odpowiedzi na pasujące żądanie.
Jeśli chcesz wyrazić wulgarność,
możesz użyć pustego pola return;
w wywołaniu zwrotnym zdarzenia fetch
dla żądań, które chcesz przekazać do sieci.
To właśnie dzieje się w przypadku opcji „Tylko pamięć podręczna” prezentację strategii dla żądań, które nie są wstępnie w pamięci podręcznej.
Najpierw pamięć podręczna, a potem powrót do sieci
W tej strategii sprawy odgrywają nieco większą rolę. W przypadku żądań dopasowania proces wygląda tak:
- Żądanie trafia do pamięci podręcznej. Jeśli zasób jest w pamięci podręcznej, uruchom go z tego miejsca.
- Jeśli żądania nie ma w pamięci podręcznej, przejdź do sieci.
- Gdy żądanie sieciowe zostanie zakończone, dodaj je do pamięci podręcznej i zwraca odpowiedź z sieci.
Oto przykład tej strategii, który możesz przetestować prezentację na żywo:
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('fetch', (event) => {
// Check if this is a request for an image
if (event.request.destination === 'image') {
event.respondWith(caches.open(cacheName).then((cache) => {
// Go to the cache first
return cache.match(event.request.url).then((cachedResponse) => {
// Return a cached response if we have one
if (cachedResponse) {
return cachedResponse;
}
// Otherwise, hit the network
return fetch(event.request).then((fetchedResponse) => {
// Add the network response to the cache for later visits
cache.put(event.request, fetchedResponse.clone());
// Return the network response
return fetchedResponse;
});
});
}));
} else {
return;
}
});
Choć ten przykład dotyczy tylko obrazów, warto ją zastosować do wszystkich zasobów statycznych (np. CSS, JavaScript, obrazy i czcionki), zwłaszcza tych z postaciami oznaczonymi haszami. Zapewnia szybsze działanie zasobów stałych, ponieważ pomija wszelkie próby sprawdzenia aktualności treści na serwerze, które może uruchomić pamięć podręczna HTTP. Co ważniejsze, wszystkie zasoby z pamięci podręcznej będą dostępne offline.
Najpierw sieć, powrót do pamięci podręcznej
Jeśli zmienisz ustawienie „Najpierw pamięć podręczna, potem sieć” na głowie, pojawia się komunikat „Najpierw sieć, potem pamięć podręczna”. strategii. Jak to brzmi:
- Najpierw wysyłasz żądanie do sieci i umieszczasz odpowiedź w pamięci podręcznej.
- Jeśli później będziesz offline, powrócisz do najnowszej wersji tej odpowiedzi w pamięci podręcznej.
Ta strategia sprawdza się świetnie w przypadku żądań HTML i API, gdy gdy jesteś online, potrzebujesz najnowszej wersji zasobu, ale chcesz przyznać dostęp offline do najnowszej dostępnej wersji. Oto, jak to może wyglądać po zastosowaniu do żądań w kodzie HTML:
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('fetch', (event) => {
// Check if this is a navigation request
if (event.request.mode === 'navigate') {
// Open the cache
event.respondWith(caches.open(cacheName).then((cache) => {
// Go to the network first
return fetch(event.request.url).then((fetchedResponse) => {
cache.put(event.request, fetchedResponse.clone());
return fetchedResponse;
}).catch(() => {
// If the network is unavailable, get
return cache.match(event.request.url);
});
}));
} else {
return;
}
});
Możesz to sprawdzić w wersji demonstracyjnej. Najpierw wejdź na daną stronę. Może być konieczne ponowne załadowanie, zanim odpowiedź HTML zostanie umieszczona w pamięci podręcznej. Następnie w narzędziach dla programistów symulację połączenia offline, i załaduj ponownie. Ostatnia dostępna wersja jest udostępniana natychmiast z pamięci podręcznej.
W sytuacjach, gdy praca w trybie offline jest ważna, ale trzeba zrównoważyć te możliwości z dostępem do najnowszych wersji znaczników lub danych API, „Najpierw sieć, potem pamięć podręczna” jest solidna strategia dążąca do osiągnięcia tego celu.
Nieaktualne – w trakcie ponownej weryfikacji
Spośród omówionych do tej pory strategii „Nieużywanie w trakcie ponownej weryfikacji” jest najbardziej złożona. Jest ona pod pewnymi względami podobna do dwóch ostatnich strategii, ale procedura nadaje priorytet szybkości dostępu do zasobu, a jednocześnie aktualizować go w tle. Strategia ta wygląda mniej więcej tak:
- Przy pierwszym żądaniu zasobu pobierz go z sieci, umieścić go w pamięci podręcznej i zwrócić odpowiedź sieciową.
- Przy kolejnych żądaniach wyświetlaj zasób najpierw z pamięci podręcznej, a potem „w tle” Wyślij żądanie ponownie z sieci i zaktualizuj wpis w pamięci podręcznej zasobu.
- W przypadku kolejnych próśb otrzymasz ostatnią pobraną z sieci wersję, która została umieszczona w pamięci podręcznej w poprzednim kroku.
To doskonała strategia w przypadku informacji, które są dość ważne, aby były zawsze aktualne, ale nie mają znaczenia. Pomyśl o takich rzeczach jak awatary do witryn w mediach społecznościowych. Są aktualizowane, gdy użytkownicy z niej korzystają, Najnowsza wersja nie jest jednak wymagana przy każdym żądaniu.
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('fetch', (event) => {
if (event.request.destination === 'image') {
event.respondWith(caches.open(cacheName).then((cache) => {
return cache.match(event.request).then((cachedResponse) => {
const fetchedResponse = fetch(event.request).then((networkResponse) => {
cache.put(event.request, networkResponse.clone());
return networkResponse;
});
return cachedResponse || fetchedResponse;
});
}));
} else {
return;
}
});
Możesz zobaczyć, jak to działa w:
kolejną prezentację na żywo,
zwłaszcza na karcie Sieć w narzędziach dla programistów przeglądarki,
i jego przeglądarki CacheStorage
(o ile dostępne w przeglądarce narzędzia dla programistów ją zawierają).
Dalej do Workbox!
Ten dokument zawiera podsumowanie informacji o interfejsie API Service Worker, oraz powiązane interfejsy API, Oznacza to, że wiesz już wystarczająco dużo o tym, jak bezpośrednio używać mechanizmów Service Worker, aby zacząć eksperymentować z Workbox.