Korzystanie z wtyczek

Podczas korzystania z Workbox możesz manipulować żądaniem i odpowiedzią, gdy są pobierane lub przechowywane w pamięci podręcznej. Wtyczki Workbox umożliwiają dodawanie dodatkowych zachowań do Twojego serwisu workera przy minimalnym nakładzie pracy. Można je spakować i wykorzystać ponownie w własnych projektach lub opublikować, aby mogli z nich korzystać inni.

Workbox oferuje wiele dostępnych w pakiecie wtyczek, a jeśli jesteś pomysłowym użytkownikiem, możesz napisać niestandardowe wtyczki dostosowane do wymagań Twojej aplikacji.

Dostępne wtyczki Workbox

Workbox udostępnia te oficjalne wtyczki do użycia w usługach:

Wtyczki Workbox (czy to wtyczki wymienione powyżej, czy wtyczki niestandardowe) są używane w strategii Workbox. Aby dodać instancję wtyczki do plugins usługi strategii:

import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';

registerRoute(
  ({request}) => request.destination === 'image',
  new CacheFirst({
    cacheName: 'images',
    plugins: [
      new ExpirationPlugin({
        maxEntries: 60,
        maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
      }),
    ],
  })
);

Metody dotyczące wtyczek niestandardowych

Wtyczka Workbox musi implementować co najmniej jedną funkcję wywołania zwrotnego. Gdy dodasz wtyczkę do strategii, funkcje wywołania zwrotnego są automatycznie wykonywane we właściwym czasie. Strategia przekazuje funkcji wywołania zwrotnego odpowiednie informacje o bieżącym żądaniu lub odpowiedzi, zapewniając wtyczce kontekst, którego potrzebuje do działania. Obsługiwane są te funkcje wywołania zwrotnego:

  • cacheWillUpdate: jest wywoływany przed użyciem metody Response do zaktualizowania pamięci podręcznej. W tej metodzie odpowiedź może zostać zmieniona przed dodaniem do pamięci podręcznej. Możesz też zwrócić null, aby uniknąć całkowitego aktualizowania pamięci podręcznej.
  • cacheDidUpdate: wywołana po dodaniu nowego wpisu do pamięci podręcznej lub aktualizacji istniejącego wpisu. Wtyczki korzystające z tej metody mogą być przydatne, gdy chcesz wykonać działanie po zaktualizowaniu pamięci podręcznej.
  • cacheKeyWillBeUsed: jest wywoływany, zanim żądanie zostanie użyte jako klucz pamięci podręcznej. Dotyczy to zarówno wyszukiwania w pamięci podręcznej (gdy mode to 'read'), jak i zapisu do pamięci podręcznej (gdy mode to 'write'). Ta funkcja zwracania wartości jest przydatna, jeśli chcesz zastąpić lub znormalizować adresy URL przed ich użyciem do uzyskiwania dostępu do pamięci podręcznej.
  • cachedResponseWillBeUsed: ta metoda jest wywoływana tuż przed użyciem odpowiedzi z pamięci podręcznej, co pozwala Ci ją sprawdzić. W tym momencie możesz zwrócić inną odpowiedź lub zwrócić null.
  • requestWillFetch: wywoływany za każdym razem, gdy żądanie trafia do sieci. Przydatne, gdy chcesz zmienić Request tuż przed wysłaniem go do sieci.
  • fetchDidFail: wywoływana, gdy żądanie sieciowe się nie powiedzie, prawdopodobnie z powodu braku połączenia z internetem. Nie zostanie wywołana, gdy przeglądarka ma połączenie z internetem, ale otrzyma błąd (np. 404 Not Found).
  • fetchDidSucceed: jest wywoływany zawsze, gdy żądanie sieciowe zakończy się powodzeniem, niezależnie od kodu odpowiedzi HTTP.
  • handlerWillStart: wywoływana przed rozpoczęciem działania logiki modułu obsługi, co jest przydatne, jeśli musisz ustawić początkowy stan modułu obsługi. Jeśli na przykład chcesz się dowiedzieć, ile czasu zajęło modułowi obsługi wygenerowanie odpowiedzi, możesz zapisać czas rozpoczęcia w wywołaniu zwrotnym.
  • handlerWillRespond: jest wywoływany, zanim metoda handle() strategii zwróci odpowiedź. Jest to przydatne, jeśli chcesz zmodyfikować odpowiedź przed jej przekazaniem do RouteHandler lub innej logiki niestandardowej.
  • handlerDidRespond: jest wywoływana po zwróceniu odpowiedzi przez metodę handle() strategii. W tym momencie warto zapisać wszelkie szczegóły ostatecznej odpowiedzi (na przykład po zmianach wprowadzonych przez inne wtyczki).
  • handlerDidComplete: jest wywoływany po ustabilizowaniu się wszystkich obietnic dotyczących przedłużenia okresu obowiązywania dodanych do zdarzenia w wywołaniu strategii. Jest to przydatne, gdy chcesz wygenerować raport o danych, które muszą czekać na zakończenie działania modułu obsługi, aby obliczać takie dane jak stan trafienia w pamięci podręcznej, czas oczekiwania w pamięci podręcznej czy czas oczekiwania w sieci.
  • handlerDidError: wywoływana, gdy moduł nie może podać prawidłowej odpowiedzi z dowolnego źródła. Jest to optymalny moment na podanie odpowiedzi zastępczej zamiast odmowy.

Wszystkie te wywołania zwrotne są async, dlatego wymagają użycia await, gdy zdarzenie dotyczące pamięci podręcznej lub pobierania dotrze do odpowiedniego punktu wywołania zwrotnego.

Jeśli w pluginie używane są wszystkie powyższe funkcje zwracania wartości, kod będzie wyglądał tak:

const myPlugin = {
  cacheWillUpdate: async ({request, response, event, state}) => {
    // Return `response`, a different `Response` object, or `null`.
    return response;
  },
  cacheDidUpdate: async ({
    cacheName,
    request,
    oldResponse,
    newResponse,
    event,
    state,
  }) => {
    // No return expected
    // Note: `newResponse.bodyUsed` is `true` when this is called,
    // meaning the body has already been read. If you need access to
    // the body of the fresh response, use a technique like:
    // const freshResponse = await caches.match(request, {cacheName});
  },
  cacheKeyWillBeUsed: async ({request, mode, params, event, state}) => {
    // `request` is the `Request` object that would otherwise be used as the cache key.
    // `mode` is either 'read' or 'write'.
    // Return either a string, or a `Request` whose `url` property will be used as the cache key.
    // Returning the original `request` will make this a no-op.
    return request;
  },
  cachedResponseWillBeUsed: async ({
    cacheName,
    request,
    matchOptions,
    cachedResponse,
    event,
    state,
  }) => {
    // Return `cachedResponse`, a different `Response` object, or null.
    return cachedResponse;
  },
  requestWillFetch: async ({request, event, state}) => {
    // Return `request` or a different `Request` object.
    return request;
  },
  fetchDidFail: async ({originalRequest, request, error, event, state}) => {
    // No return expected.
    // Note: `originalRequest` is the browser's request, `request` is the
    // request after being passed through plugins with
    // `requestWillFetch` callbacks, and `error` is the exception that caused
    // the underlying `fetch()` to fail.
  },
  fetchDidSucceed: async ({request, response, event, state}) => {
    // Return `response` to use the network response as-is,
    // or alternatively create and return a new `Response` object.
    return response;
  },
  handlerWillStart: async ({request, event, state}) => {
    // No return expected.
    // Can set initial handler state here.
  },
  handlerWillRespond: async ({request, response, event, state}) => {
    // Return `response` or a different `Response` object.
    return response;
  },
  handlerDidRespond: async ({request, response, event, state}) => {
    // No return expected.
    // Can record final response details here.
  },
  handlerDidComplete: async ({request, response, error, event, state}) => {
    // No return expected.
    // Can report any data here.
  },
  handlerDidError: async ({request, event, error, state}) => {
    // Return a `Response` to use as a fallback, or `null`.
    return fallbackResponse;
  },
};

Obiekt event dostępny w wywołaniach zwrotnych wymienionych powyżej to pierwotne zdarzenie, które wywołało działanie pobierania lub pamięci podręcznej. Czasami nie będzie to zdarzenie oryginalne, dlatego Twój kod powinien sprawdzić, czy istnieje, zanim się do niego odniesie.

Wszystkie wywołania zwrotne wtyczki są również przekazywane do obiektu state, który jest unikalny dla konkretnej wtyczki i wywoływanej przez nią strategii. Oznacza to, że możesz pisać wtyczki, w których jedna funkcja wywołania zwrotnego może warunkowo wykonywać zadanie na podstawie tego, co zrobiła inna funkcja wywołania zwrotnego w tym samym pliku wtyczki (np. obliczać różnicę między wykonaniem funkcji requestWillFetch()fetchDidSucceed() lub fetchDidFail()).

Wtyczki innych firm

Jeśli utworzysz wtyczkę i uważasz, że może być używana poza Twoim projektem, zachęcamy do opublikowania jej jako modułu. Poniżej znajduje się krótka lista wtyczek Workbox udostępnionych przez społeczność:

Możesz znaleźć więcej wtyczek Workbox udostępnionych przez społeczność, przeszukując repozytorium npm.

Jeśli masz już wtyczkę Workbox, którą chcesz udostępnić, dodaj workbox-plugin słowo kluczowe podczas publikowania. Jeśli tak, daj nam znać na Twitterze, pisząc do nas na konto @WorkboxJS.