Niektóre strony mogą wymagać komunikacji z skryptem service worker bez konieczności poinformować o wyniku. Oto przykłady:
- Strona wysyła do mechanizmu Service Worker listę adresów URL, do których pobierania z wyprzedzeniem. Dzięki temu, gdy użytkownik kliknie linki do zasobów podrzędnych dokumentu lub strony są już dostępne w pamięci podręcznej, dzięki czemu kolejne nawigacja działa znacznie szybciej.
- Strona prosi skrypt service worker o pobranie i zapisanie w pamięci podręcznej zbioru najpopularniejszych artykułów, aby zostały do użytku w trybie offline.
Przekazywanie tego typu niekrytycznych zadań skryptowi service worker pozwala zwolnić w głównym wątku, aby ułatwić sobie wykonywanie pilniejszych zadań, takich jak odpowiadanie na interakcje użytkowników.
W tym przewodniku pokażemy, jak wdrożyć technikę jednokierunkowej komunikacji ze strony skrypt service worker za pomocą standardowych interfejsów API przeglądarki i biblioteki Workbox. Tego typu reklamy będziemy nazywać imperatywnym buforowaniu.
Sceneria produkcyjna
Firma 1-800-Flowers.com wdrożyła imperatywne buforowanie (wstępne pobieranie) z mechanizmami Service Worker za pomocą
postMessage()
, aby pobrać z wyprzedzeniem
najpopularniejszych pozycji na stronach kategorii, aby przyspieszyć nawigację do stron ze szczegółami produktów.
Stosują mieszane podejście, aby zdecydować, które elementy pobrać z wyprzedzeniem:
- Podczas wczytywania strony prosi on skrypt servicer o pobranie danych JSON 9 pierwszych elementów. dodać wynikowe obiekty odpowiedzi do pamięci podręcznej.
- Pozostałe elementy słuchają (
mouseover
) . W takim przypadku gdy użytkownik najedzie kursorem na element, może uruchomić pobieranie zasobu na żądanie.
Do przechowywania plików JSON używają interfejsu Cache API. odpowiedzi:
Gdy użytkownik kliknie produkt, powiązane z nim dane JSON zostaną pobrane z pamięci podręcznej. bez konieczności łączenia się z siecią, co przyspiesza nawigację.
Korzystanie z Workbox
Workbox umożliwia łatwe wysyłanie wiadomości do
skrypt service worker za pomocą pakietu workbox-window
, czyli zestawu modułów
które powinny działać
w kontekście okna. Stanowią uzupełnienie innych pakietów Workbox.
działające w skrypcie service worker.
Aby przekazać stronę z skryptem service worker, najpierw uzyskaj odniesienie do obiektu Workbox do zarejestrowany skrypt service worker:
const wb = new Workbox('/sw.js');
wb.register();
Następnie możesz wysłać wiadomość bezpośrednio deklaratywnie, bez konieczności pobierania rejestracji, sprawdzenia możliwości aktywacji lub myślenia o interfejsie API do komunikacji:
wb.messageSW({"type": "PREFETCH", "payload": {"urls": ["/data1.json", "data2.json"]}}); });
Skrypt service worker implementuje moduł obsługi message
, aby
nasłuchać tych wiadomości. Opcjonalnie może zwrócić odpowiedź, ale w takich przypadkach jest
niewymagane:
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'PREFETCH') {
// do something
}
});
Korzystanie z interfejsów API przeglądarki
Jeśli biblioteka Workbox nie wystarcza do Twoich potrzeb, możesz wdrożyć usługi typu window-to Service w ten sposób. komunikacji między pracownikami za pomocą interfejsów API w przeglądarkach.
Interfejs postMessage API mogą posłużyć do ustanowienia jednokierunkowego mechanizmu komunikacji między stroną a skrypcją service worker.
Strona wywołuje
postMessage()
interfejs skryptu service worker:
navigator.serviceWorker.controller.postMessage({
type: 'MSG_ID',
payload: 'some data to perform the task',
});
Skrypt service worker implementuje moduł obsługi message
, aby
nasłuchać tych wiadomości.
self.addEventListener('message', (event) => {
if (event.data && event.data.type === MSG_ID) {
// do something
}
});
Atrybut {type : 'MSG_ID'}
nie jest absolutnie wymagany, ale jest to jeden ze sposobów zezwolenia strony na
wysyłanie różnych typów instrukcji do skryptu service worker (np. „pobieranie z wyprzedzeniem” i „pobieranie z wyprzedzeniem”
pamięci masowej”). Skrypt service worker może na podstawie tej flagi rozgałęziać się na różne ścieżki wykonania.
Jeśli operacja się uda, użytkownik będzie mógł czerpać z niej korzyści, ale w przeciwnym razie nie wpłynie to na główny proces użytkownika. Gdy na przykład 1-800-Flowers.com próbuje wstępnie buforować dane, strona nie musi wiedzieć, czy skrypt service worker się udał. Jeśli tak, użytkownicy będą mogli korzystać z szybszej nawigacji. Jeśli tak się nie stanie, musisz przejść na nową stronę. Potrwa to tylko trochę dłużej.
Prosty przykład pobierania z wyprzedzeniem
Jednym z najczęstszych zastosowań imperatywnego buforowania jest wstępne pobieranie, które polega na pobieraniu treści. zasobów dla danego adresu URL, zanim użytkownik przejdzie do niego, aby przyspieszyć nawigację.
W witrynach można wdrożyć pobieranie z wyprzedzeniem na różne sposoby:
- Użycie na stronach tagów pobierania z wyprzedzeniem linków: zasoby są przechowywane w folderach
pamięci podręcznej przeglądarki na pięć minut, po upływie których normalne reguły
Cache-Control
dla zasobu zastosuj. - Uzupełnienie poprzedniej metody o strategię buforowania czasu działania w usłudze instancja robocza, aby przedłużyć czas pobierania z wyprzedzeniem. zasobów ponad ten limit.
W przypadku stosunkowo prostych scenariuszy pobierania z wyprzedzeniem, takich jak wstępne pobieranie dokumentów lub konkretne zasoby (JS, CSS itd.), te techniki są najlepsze.
Jeśli wymagane są dodatkowe mechanizmy logiczne, np. analiza zasobu pobierania z wyprzedzeniem (plik JSON lub strony) w pobierania wewnętrznych adresów URL, lepiej jest przekazać to zadanie w całości skrypt service worker.
Przekazywanie tego typu operacji do skryptu service worker ma następujące zalety:
- Nie wymaga to ciężkiej pracy z pobieraniem i przetwarzaniem po pobieraniu (co zostanie wprowadzone później) do wątku dodatkowego. Dzięki temu wątek główny będzie obsługiwał ważniejsze takich jak reagowanie na interakcje użytkowników.
- Umożliwienie wielu klientom (np. kart) korzystania ze wspólnej funkcji, a nawet wywoływaniu funkcji jednocześnie bez blokowania wątku głównego.
Wstępnie pobieraj strony ze szczegółami produktów
Pierwsze użycie postMessage()
interfejsu mechanizmu Service Worker i przekazać tablicę adresów URL do pamięci podręcznej:
navigator.serviceWorker.controller.postMessage({
type: 'PREFETCH',
payload: {
urls: [
'www.exmaple.com/apis/data_1.json',
'www.exmaple.com/apis/data_2.json',
],
},
});
W skrypcie service worker zaimplementuj moduł obsługi message
, aby
przechwytuj i przetwarzaj wiadomości wysyłane przez dowolną aktywną kartę:
addEventListener('message', (event) => {
let data = event.data;
if (data && data.type === 'PREFETCH') {
let urls = data.payload.urls;
for (let i in urls) {
fetchAsync(urls[i]);
}
}
});
W poprzednim kodzie wprowadziliśmy małą funkcję pomocniczą o nazwie fetchAsync()
, która służy do iteracji
tablicę adresów URL i wysyłać dla każdego z nich żądanie pobrania:
async function fetchAsync(url) {
// await response of fetch call
let prefetched = await fetch(url);
// (optionally) cache resources in the service worker storage
}
Po uzyskaniu odpowiedzi możesz polegać na nagłówkach buforowania zasobu. W wielu przypadkach
Tak jak na stronach ze szczegółami produktów, zasoby nie są przechowywane w pamięci podręcznej (co oznacza, że mają
Cache-control
nagłówek no-cache
). W takich przypadkach możesz zmienić ten sposób działania, przez
zapisując pobrany zasób w pamięci podręcznej mechanizmu Service Worker. Ma to też dodatkową zaletę:
który ma być wyświetlany w sytuacjach offline.
Nie tylko dane JSON
Po pobraniu danych JSON z punktu końcowego serwera często zawierają one inne adresy URL, które również które warto pobrać z wyprzedzeniem, np. obrazu lub innych danych punktu końcowego, które są powiązane z danym pierwszym poziomem i skalowalnych danych.
Załóżmy, że w naszym przykładzie zwracane dane JSON to informacje o witrynie sklepu spożywczego:
{
"productName": "banana",
"productPic": "https://cdn.example.com/product_images/banana.jpeg",
"unitPrice": "1.99"
}
Zmodyfikuj kod fetchAsync()
, aby iterować listę produktów i buforować baner powitalny dla
każdy z nich:
async function fetchAsync(url, postProcess) {
// await response of fetch call
let prefetched = await fetch(url);
//(optionally) cache resource in the service worker cache
// carry out the post fetch process if supplied
if (postProcess) {
await postProcess(prefetched);
}
}
async function postProcess(prefetched) {
let productJson = await prefetched.json();
if (productJson && productJson.product_pic) {
fetchAsync(productJson.product_pic);
}
}
W razie wystąpienia błędu 404 możesz też dodać obsługę wyjątków w tym kodzie. Urok stosowania skryptu service worker do pobierania z wyprzedzeniem polega na tym, że może się on w stosunku do treści na stronie i w wątku głównym. Możliwe też, że bardziej złożone logiki są bardziej elastyczne i oddzielne od danych. z obsługą klienta. Nie ma żadnych ograniczeń.
Podsumowanie
W tym artykule omówiliśmy typowy przypadek użycia jednokierunkowej komunikacji między stroną a usługą instancja robocza: imperatywne buforowanie. Omawiane przykłady mają zademonstrować tylko jeden sposób Wykorzystując ten wzorzec i to samo podejście, można je zastosować również do innych przypadków użycia, np. Zapisywanie najpopularniejszych artykułów na żądanie w pamięci podręcznej, aby można je było przeglądać offline, dodawać do zakładek itp.
Więcej wzorców komunikacji stron i mechanizmów Service Worker znajdziesz tutaj:
- Aktualizacje komunikatów: wywołuje stronę z poziomu skryptu service worker w celu przekazania informacji o ważnych aktualizacjach (np. o nowej wersji aplikacji internetowej).
- Komunikacja dwukierunkowa: przekazywanie zadania do skryptu service worker (np. pobieranie dużych ilości danych) oraz informowanie strony o postępach.