Como gerenciar respostas substitutas

Em determinadas situações, você pode querer uma resposta substituta armazenada em cache caso o usuário esteja off-line. Implementar um substituto é uma alternativa aos comportamentos de armazenamento em cache oferecidos por estratégias como priorização da rede ou revalidação obsoleta.

Um substituto é uma resposta genérica que serve para todos os casos e é um marcador de posição melhor do que o navegador forneceria por padrão quando uma solicitação falhasse. Por exemplo:

  • Uma alternativa à "imagem ausente" marcador de posição.
  • Uma alternativa em HTML ao padrão "sem conexão de rede disponível" página.

Somente página off-line

Se tudo o que você precisa fazer é fornecer uma página HTML off-line personalizada e nada mais, aqui está um roteiro de referência que você pode seguir:

import {offlineFallback} from 'workbox-recipes';
import {setDefaultHandler} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

setDefaultHandler(new NetworkOnly());

offlineFallback();

O código acima usa setDefaultHandler para aplicar uma estratégia somente de rede como padrão para todas as rotas. Em seguida, ele executa o roteiro offlineFallback para exibir o substituto off-line caso ocorra um erro. O roteiro pressupõe que o arquivo HTML substituto off-line será chamado offline.html e veiculado a partir da raiz do seu servidor da Web.

Substitutos abrangentes

Sempre que ocorre uma falha de rede ou ausência no cache, as estratégias de armazenamento em cache oferecidas por workbox-strategies são rejeitadas de forma consistente. Isso promove o padrão de definição de um "catch" global para lidar com falhas em uma única função de gerenciador, o que permite oferecer substitutos diferentes para valores de request.destination distintos.

O exemplo a seguir usa o roteiro warmStrategyCache de workbox-recipes e define um gerenciador de captura para exibir itens armazenados em cache com antecedência no cache do ambiente de execução. No entanto, o armazenamento em cache substituto pode ser uma opção melhor para seu aplicativo:

import {warmStrategyCache} from 'workbox-recipes';
import {setDefaultHandler, setCatchHandler} from 'workbox-routing';
import {CacheFirst, StaleWhileRevalidate} from 'workbox-strategies';

// Fallback assets to cache
const FALLBACK_HTML_URL = '/offline.html';
const FALLBACK_IMAGE_URL = '/images/image-not-found.jpg';
const FALLBACK_STRATEGY = new CacheFirst();

// Warm the runtime cache with a list of asset URLs
warmStrategyCache({
  urls: [FALLBACK_HTML_URL, FALLBACK_IMAGE_URL],
  strategy: FALLBACK_STRATEGY,
});

// Use a stale-while-revalidate strategy to handle requests by default.
setDefaultHandler(new StaleWhileRevalidate());

// This "catch" handler is triggered when any of the other routes fail to
// generate a response.
setCatchHandler(async ({request}) => {
  // The warmStrategyCache recipe is used to add the fallback assets ahead of
  // time to the runtime cache, and are served in the event of an error below.
  // Use `event`, `request`, and `url` to figure out how to respond, or
  // use request.destination to match requests for specific resource types.
  switch (request.destination) {
    case 'document':
      return FALLBACK_STRATEGY.handle({event, request: FALLBACK_HTML_URL});

    case 'image':
      return FALLBACK_STRATEGY.handle({event, request: FALLBACK_IMAGE_URL});

    default:
      // If we don't have a fallback, return an error response.
      return Response.error();
  }
});

A seguir, as respostas de substituição são pré-armazenadas em cache usando injectManifest com as ferramentas de build do Workbox e veiculadas como substitutos no caso de um erro com o método matchPrecache.

import {matchPrecache, precacheAndRoute} from 'workbox-precaching';
import {setDefaultHandler, setCatchHandler} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';

// Optional: use the injectManifest mode of one of the Workbox
// build tools to precache a list of URLs, including fallbacks.
precacheAndRoute(self.__WB_MANIFEST);

// Use a stale-while-revalidate strategy to handle requests by default.
setDefaultHandler(new StaleWhileRevalidate());

// This "catch" handler is triggered when any of the other routes fail to
// generate a response.
setCatchHandler(async ({request}) => {
  // Fallback assets are precached when the service worker is installed, and are
  // served in the event of an error below. Use `event`, `request`, and `url` to
  // figure out how to respond, or use request.destination to match requests for
  // specific resource types.
  switch (request.destination) {
    case 'document':
      // FALLBACK_HTML_URL must be defined as a precached URL for this to work:
      return matchPrecache(FALLBACK_HTML_URL);

    case 'image':
      // FALLBACK_IMAGE_URL must be defined as a precached URL for this to work:
      return matchPrecache(FALLBACK_IMAGE_URL);

    default:
      // If we don't have a fallback, return an error response.
      return Response.error();
  }
});

Um exemplo de caso de uso para a segunda configuração de substituto é se uma página tiver sido armazenada em cache com antecedência, mas as imagens (ou outros recursos) solicitadas pela página não foram. A página ainda pode ser lida no cache quando o usuário está off-line, mas marcadores de posição substitutos ou uma funcionalidade alternativa podem ser fornecidos se ocorrer um erro de rede.

Como aquecer o cache do ambiente de execução

O Workbox mantém caches separados para o pré-armazenamento em cache e os caches de tempo de execução. Pode haver situações em que você queira armazenar em cache algo com antecedência, sem depender de pré-armazenamento, já que as atualizações no manifesto do pré-cache exigirão a implantação de um service worker atualizado.

Para preparar o cache do ambiente de execução com recursos, use o roteiro warmStrategyCache de workbox-recipes. Internamente, essa estratégia chama Cache.addAll no evento install de um service worker.

import {warmStrategyCache} from 'workbox-recipes';
import {CacheFirst} from 'workbox-strategies';

// This can be any strategy, CacheFirst used as an example.
const strategy = new CacheFirst();
const urls = [
  '/offline.html',
];

warmStrategyCache({urls, strategy});

Conclusão

Gerenciar respostas substitutas para solicitações com falha exige um pouco de trabalho, mas, com um pouco de planejamento antecipado, você pode configurar seu aplicativo da Web para fornecer algum nível de conteúdo e funcionalidade quando o usuário estiver off-line.