Funkcje natychmiastowej nawigacji

Uzupełnianie tradycyjnych technik wstępnego pobierania za pomocą usług.

Wykonywanie zadania w witrynie zwykle wymaga wykonania kilku czynności. Na przykład zakup produktu w witrynie e-commerce może obejmować wyszukanie produktu, wybranie go z listy wyników, dodanie do koszyka i dokonanie płatności.

W języku technicznym przewijanie różnych stron oznacza wysyłanie żądania nawigacji. Zwykle nie używa się długotrwałych nagłówków Cache-Control do umieszczania w pamięci podręcznej odpowiedzi HTML na żądanie nawigacyjne. Zwykle powinny one być spełnione przez sieć za pomocą Cache-Control: no-cache, aby zapewnić, że kod HTML wraz z łańcuchem kolejnych żądań sieciowych jest (w miarę) aktualny. Wymagana zmiana sieci za każdym razem, gdy użytkownik przechodzi na nową stronę, może niestety oznaczać, że każda zmiana może być powolna, a co najmniej nie będzie zawsze szybka.

Aby przyspieszyć te żądania, jeśli możesz przewidzieć działanie użytkownika, możesz z wyprzedzeniem poprosić o te strony i komponenty oraz przechowywać je w pamięci podręcznej przez krótki czas, aż użytkownik kliknie te linki. Ta metoda nazywa się pobieraniem z wyprzedzeniem i zwykle jest wdrażana przez dodanie do stron tagów <link rel="prefetch">, które wskażą zasób do pobrania z wyprzedzeniem.

W tym przewodniku omówimy różne sposoby stosowania skryptów service worker jako uzupełnienie tradycyjnych technik pobierania z wyprzedzeniem.

Sprawy produkcyjne

MercadoLibre to największa witryna e-commerce w Ameryce Łacińskiej. Aby przyspieszyć nawigację, dynamicznie wstrzykują tagi <link rel="prefetch"> w niektórych częściach procesu. Na przykład na stronach z listą wyników pobieranie następnej strony wyników następuje, gdy użytkownik przewinie stronę do samego dołu:

Zrzut ekranu przedstawiający stronę nr 1 i 2 w MercadoLibre oraz tag pobierania z wyprzedzeniem, który łączy obie strony.

Pliki pobrane w poprzednim czasie są pobierane z priorytetem „Najniższy” i przechowywane w pamięci podręcznej HTTP lub pamięci podręcznej (w zależności od tego, czy zasób można przechowywać w pamięci podręcznej), przez czas, który różni się w zależności od przeglądarki. Na przykład w wersji Chrome 85 ta wartość wynosi 5 minut. Zasoby są przechowywane przez 5 minut, po których obowiązują normalne zasady Cache-Control dotyczące zasobu.

Korzystanie z buforowania w ramach usługi workera może wydłużyć czas życia zasobów z wyprzedzeniem poza 5-minutowy limit.

Na przykład włoski portal sportowy Virgilio Sport używa usług workerów do wstępnego pobierania najpopularniejszych postów na stronie głównej. Korzystają też z interfejsu Network Information API, aby uniknąć pobierania w tle w przypadku użytkowników korzystających z połączenia 2G.

Logo Virgilio Sport.

W wyniku tych działań w ciągu 3 tygodni czas wczytywania stron z artykułami skrócił się o 78%, a liczba wyświetleń artykułów wzrosła o 45%.

Zrzut ekranu strony głównej i artykułów na stronie Virgilio Sport z danymi dotyczącymi wpływu po pobraniu z wyprzedzeniem.

Wdrażanie wstępnego buforowania w Workbox

W następnej sekcji użyjemy Workbox, aby pokazać, jak wdrożyć w skrypcie service worker różne techniki buforowania, których można użyć jako uzupełnienie metody <link rel="prefetch"> lub nawet jej zastąpienie, całkowicie przekazując to zadanie skryptowi service worker.

1. Wstępne buforowanie stron statycznych i podzasobów stron

Przedwczesna pamięć podręczna to możliwość zapisywania plików w pamięci podręcznej przez usługę w trakcie instalacji.

W tych przypadkach wstępne buforowanie jest używane do osiągnięcia celu podobnego do wstępnego pobierania: przyspieszenia nawigacji.

Wstępne wczytywanie stron statycznych

W przypadku stron wygenerowanych w czasie kompilacji (np. about.html, contact.html) lub w całkowicie statycznych witrynach można po prostu dodać dokumenty z tej witryny do listy Precache, tak aby były one dostępne w pamięci podręcznej za każdym razem, gdy użytkownik korzysta z nich:

workbox.precaching.precacheAndRoute([
  {url: '/about.html', revision: 'abcd1234'},
  // ... other entries ...
]);

Wstępne wczytywanie podzasobów strony

Wstępne pobieranie statycznych zasobów, których mogą używać różne sekcje witryny (np. JavaScript, CSS itp.), to ogólna zalecana praktyka, która może dodatkowo zwiększyć wydajność w scenariuszach wstępnego pobierania.

Aby przyspieszyć nawigację w witrynie e-commerce, możesz użyć tagów <link rel="prefetch"> na stronach z informacjami o produkcie, aby z wyprzedzeniem pobrać strony ze szczegółami pierwszych kilku produktów na stronie z informacjami o produkcie. Jeśli masz już w pamięci podręcznej wstępnie zasoby podrzędne strony produktu, może to jeszcze bardziej przyspieszyć nawigację.

Aby to zrobić:

  • Dodaj do strony tag <link rel="prefetch">:
 <link rel="prefetch" href="/phones/smartphone-5x.html" as="document">
  • Dodaj podzasoby strony do listy zasobów do wcześniejszego buforowania w usługach:
workbox.precaching.precacheAndRoute([
  '/styles/product-page.ac29.css',
  // ... other entries ...
]);

2. Wydłuż czas przechowywania zasobów pobierania z wyprzedzeniem

Jak wspomnieliśmy wcześniej, <link rel="prefetch"> pobiera zasoby i przechowuje je w pamięci podręcznej HTTP przez ograniczony czas, po którym zaczynają obowiązywać reguły Cache-Control dotyczące danego zasobu. Od wersji Chrome 85 ta wartość wynosi 5 minut.

Usługa workera umożliwia wydłużenie czasu działania stron z zasobami wstępnie pobieranymi, a także udostępnienie tych zasobów do użytku offline.

W poprzednim przykładzie można uzupełnić pole <link rel="prefetch"> używane do wstępnego pobierania strony produktu strategią buforowania środowiska wykonawczego Workspace.

Aby to zrobić:

  • Dodaj do strony tag <link rel="prefetch">:
 <link rel="prefetch" href="/phones/smartphone-5x.html" as="document">
  • W przypadku tych typów żądań wprowadź w instancji roboczej usług strategię buforowania w czasie działania:
new workbox.strategies.StaleWhileRevalidate({
  cacheName: 'document-cache',
  plugins: [
    new workbox.expiration.Plugin({
      maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
    }),
  ],
});

W tym przypadku zdecydowaliśmy się na strategię sprawdzania poprawności po upływie określonego czasu. W ramach tej strategii żądania stron mogą być wysyłane równolegle z pamięci podręcznej i z sieci. Odpowiedź pochodzi z pamięci podręcznej, jeśli jest dostępna. W przeciwnym razie z sieci. Pamięć podręczna jest zawsze aktualizowana w odpowiedzi na żądanie sieci przy każdym udanym żądaniu.

3. Przekazywanie pobierania w tle do usługi workera

W większości przypadków najlepszym rozwiązaniem jest użycie <link rel="prefetch">. Tag to wskazówka dotycząca zasobów, która ma na celu zwiększenie efektywności wstępnego pobierania.

W niektórych przypadkach lepiej jednak całkowicie powierzyć to zadanie usługowemu procesowi w tle. Na przykład: aby z wyprzedzeniem pobrać kilka pierwszych produktów na stronie z informacjami o produkcie renderowanej po stronie klienta, może być konieczne dynamiczne wstrzyknięcie na stronie kilku tagów <link rel="prefetch"> na podstawie odpowiedzi interfejsu API. Może to chwilowo zająć czas w głównym wątku strony i utrudnić implementację.

W takich przypadkach użyj strategii komunikacji „strona do workera usługi”, aby całkowicie zlecić zadanie wstępnego pobierania workerowi usługi. Ten typ komunikacji można uzyskać za pomocą funkcji worker.postMessage():

Ikona strony dwukierunkowej komunikacji z mechanizmem Service Worker.

Pakiet okna Workbox upraszcza ten rodzaj komunikacji, abstrahując wiele szczegółów wywołania.

Pobieranie z wyprzedzeniem za pomocą okna Workbox można zaimplementować w następujący sposób:

  • Na stronie wywołaj skrypt service worker, który przekazuje mu typ wiadomości, oraz listę adresów URL do pobrania z wyprzedzeniem:
const wb = new Workbox('/sw.js');
wb.register();

const prefetchResponse = await wb.messageSW({type: 'PREFETCH_URLS', urls: []});
  • W skrypcie service worker: zaimplementuj przetwarzacz wiadomości, aby wysyłać żądanie fetch() dla każdego adresu URL, który ma być pobierany z zapoprzedzeniem:
addEventListener('message', (event) => {
  if (event.data.type === 'PREFETCH_URLS') {
    // Fetch URLs and store them in the cache
  }
});