Migrar do Workbox v4 para v5

O foco deste guia são as alterações interruptivas apresentadas no Workbox v5, com exemplos das mudanças que você precisaria fazer ao fazer upgrade do Workbox v4.

Alterações importantes

Classes do plug-in renomeadas

Vários pacotes do Workbox v4 incluíam classes com o nome Plugin. Na v5, essas classes foram renomeadas para seguir o identificador do pacote padrão + Plugin:

  • BackgroundSyncPlugin
  • BroadcastUpdatePlugin
  • CacheableResponsePlugin
  • ExpirationPlugin
  • RangeRequestsPlugin

Essa renomeação se aplica se você estiver usando as classes por importações de módulos ou namespaces workbox.*.

Ponto de substituição de manifesto de pré-cache padrão

Anteriormente, ao usar uma das ferramentas de build no modo "Injetar manifesto", o arquivo do service worker de origem era verificado quanto à presença de precacheAndRoute([]), com a matriz vazia [] usada como um marcador do ponto em que o manifesto de pré-cache era injetado.

No Workbox v5, a lógica de substituição mudou, e agora self.__WB_MANIFEST é usado por padrão como o ponto de injeção.

// v4:
precacheAndRoute([]);

// v5:
precacheAndRoute(self.__WB_MANIFEST);

Conforme descrito nesta discussão, acreditamos que essa mudança oferece uma experiência mais simples e, ao mesmo tempo, dá aos desenvolvedores mais controle sobre como o manifesto injetado é usado no código de service worker personalizado. Se necessário, é possível mudar essa string de substituição usando a opção de configuração injectionPoint.

Duas opções que anteriormente ofereciam suporte para as rotas de navegação, blacklist e whitelist, foram renomeadas como denylist e allowlist.

Anteriormente, workbox-routing oferecia suporte a um método, registerNavigationRoute(), que, em segundo plano, fazia duas coisas:

  1. Detectado se um determinado evento fetch tinha ou não um mode de 'navigate'.
  2. Em caso afirmativo, respondeu a essa solicitação usando o conteúdo de um URL previamente armazenado em cache e fixado no código, independentemente do URL que está sendo acessado.

Esse é um padrão comum para implementar a arquitetura de shell do app.

A segunda etapa, gerar uma resposta com a leitura do cache, está fora das responsabilidades da workbox-routing. Em vez disso, vemos isso como uma funcionalidade que precisa fazer parte do workbox-precaching, usando um novo método, createHandlerBoundToURL(). Esse novo método pode trabalhar em conjunto com a classe NavigationRoute já existente em workbox-routing para realizar a mesma lógica.

Se você estiver usando a opção navigateFallback em um dos modo "generate SW" da ferramenta de build, a alternância ocorrerá automaticamente. Se você já tiver configurado as opções navigateFallbackBlacklist ou navigateFallbackWhitelist, mude-as para navigateFallbackDenylist ou navigateFallbackAllowlist, respectivamente.

Se você estiver usando o modo "injetar manifesto" ou apenas criando o service worker e o service worker do Workbox v4 chamar registerNavigationRoute() diretamente, será necessário fazer uma mudança no seu código para ter o comportamento equivalente.

// v4:
import {getCacheKeyForURL} from 'workbox-precaching';
import {registerNavigationRoute} from 'workbox-routing';

const appShellCacheKey = getCacheKeyForURL('/app-shell.html');
registerNavigationRoute(appShellCacheKey, {
  whitelist: [...],
  blacklist: [...],
});

// v5:
import {createHandlerBoundToURL} from 'workbox-precaching';
import {NavigationRoute, registerRoute} from 'workbox-routing';

const handler = createHandlerBoundToURL('/app-shell.html');
const navigationRoute = new NavigationRoute(handler, {
  allowlist: [...],
  denylist: [...],
});
registerRoute(navigationRoute);

Não é mais necessário chamar getCacheKeyForURL(), já que createHandlerBoundToURL() vai cuidar disso para você.

Remoção de makeRequest() de estratégias de caixa de trabalho.

Chamar makeRequest() é quase equivalente a chamar handle() em uma das classes workbox-strategy. As diferenças entre os dois métodos eram tão pequenas que manter os dois não fazia sentido. Os desenvolvedores que chamaram makeRequest() poderão passar a usar handle() sem qualquer mudança:

// v4:
const strategy = new StaleWhileRevalidate({...});
const response = await strategy.makeRequest({event, request});

// v5:
const strategy = new StaleWhileRevalidate({...});
const response = await strategy.handle({event, request});

Na v5, handle() trata request como um parâmetro obrigatório e não voltará a usar event.request. Transmita uma solicitação válida ao chamar handle().

workbox-broadcast-update sempre usa postMessage()

Na v4, a biblioteca workbox-broadcast-update usava a API Broadcast Channel por padrão para enviar mensagens quando havia suporte e voltaria a usar postMessage() somente quando o Canal de transmissão não estava disponível.

Percebemos que ter que ouvir duas possíveis fontes de mensagens recebidas tornava a escrita de código do lado do cliente muito complicada. Além disso, em alguns navegadores, as chamadas postMessage() do service worker enviadas para páginas de clientes são automaticamente armazenadas em buffer até que um listener de eventos message seja configurado. Não há armazenamento em buffer com a API Broadcast Channel, e as mensagens transmitidas serão descartadas se forem enviadas antes que uma página do cliente esteja pronta para recebê-las.

Por esses motivos, mudamos workbox-broadcast-update para sempre usar postMessage() na v5. As mensagens são enviadas uma a uma para todas as páginas do cliente no escopo do service worker atual.

Para acomodar esse novo comportamento, você pode remover qualquer código existente em páginas de clientes que criaram instâncias BroadcastChannel e, em vez disso, configurar um listener de eventos message em navigator.serviceWorker:

// v4:
const updatesChannel = new BroadcastChannel('api-updates');
updatesChannel.addEventListener('message', event => {
  const {cacheName, updatedUrl} = event.data.payload;
  // ... your code here ...
});

// v5:
// This listener should be added as early as possible in your page's lifespan
// to ensure that messages are properly buffered.
navigator.serviceWorker.addEventListener('message', event => {
  // Optional: ensure the message came from workbox-broadcast-update
  if (event.meta === 'workbox-broadcast-update') {
    const {cacheName, updatedUrl} = event.data.payload;
    // ... your code here ...
  }
});

Os usuários do workbox-window não precisam fazer mudanças, já que a lógica interna foi atualizada para detectar chamadas postMessage().

O Build Tools exige o Node.js v8 ou mais recente

As versões do Node.js anteriores à v8 não são mais compatíveis com workbox-webpack-plugin, workbox-build ou workbox-cli. Se você estiver executando uma versão do Node.js anterior à 8, atualize o ambiente de execução para uma versão compatível.

workbox-webpack-plugin Requer webpack v4 ou superior

Se você estiver usando workbox-webpack-plugin, atualize a configuração do webpack para usar pelo menos o webpack v4.

Revisão de opções de ferramenta de build

Vários parâmetros de configuração workbox-build, workbox-cli e workbox-webpack-plugin não são mais compatíveis. Por exemplo, o generateSW sempre cria um pacote local de ambiente de execução do Workbox para você, então a opção importWorkboxFrom não faz mais sentido.

Consulte a documentação da ferramenta relevante para ver as listas de opções compatíveis.

Remoção de generateSWString do workbox-build.

O modo generateSWString foi removido do workbox-build Esperamos que o impacto seja mínimo, já que ele foi usado principalmente internamente pelo workbox-webpack-plugin.

Alterações opcionais

Como usar importações de módulo

Embora essa mudança seja a) opcional e b) fosse tecnicamente possível ao usar o Workbox v4, a maior mudança esperada ao migrar para a v5 é um modelo em que você cria seu próprio service worker em pacote importando os módulos do Workbox. Essa abordagem é uma alternativa à chamada de importScripts('/path/to/workbox-sw.js') na parte de cima do service worker e ao uso do Workbox pelo namespace workbox.*.

Se você estiver usando uma das ferramentas de build (workbox-webpack-plugin, workbox-build, workbox-cli) no modo "generate SW", essa mudança acontecerá automaticamente. Todas essas ferramentas vão gerar um pacote local personalizado do ambiente de execução do Workbox com o código real necessário para implementar a lógica do service worker. Nesse cenário, não há mais dependência do workbox-sw ou da cópia da CDN do Workbox. Dependendo do valor da configuração do inlineWorkboxRuntime, o ambiente de execução do Workbox será dividido em um arquivo separado que precisa ser implantado com o service worker (quando definido como false, que é o padrão) ou incluído inline com a lógica do service worker (quando definido como true).

Se você estiver usando as ferramentas de build no modo "injetar manifesto" ou não estiver usando as ferramentas de build do Workbox, saiba mais sobre como criar seu próprio pacote de ambiente de execução no guia Como usar Bundlers (webpack/Rollup) com o Workbox.

A documentação e os exemplos da v5 são gravados presumindo que a sintaxe importa o módulo, embora o namespace workbox.* continue tendo suporte no Workbox v5.

Como ler respostas pré-armazenadas em cache

Alguns desenvolvedores precisam ler as respostas em pré-cache diretamente do cache, em vez de usá-las implicitamente com o método precacheAndRoute(). Um padrão comum na v4 seria primeiro acessar a chave de cache específica da versão atual de um recurso pré-armazenado em cache e, em seguida, transmitir essa chave com o nome do cache do pré-cache para caches.match() para receber o Response.

Para simplificar esse processo, o workbox-precaching na v5 oferece suporte a um novo método equivalente, matchPrecache():

// v4:
import {cacheNames} from 'workbox-core';
import {getCacheKeyForURL} from 'workbox-precaching';

const cachedResponse = await caches.match(
  getCacheKeyForURL(`/somethingPrecached`),
  {
    cacheName: cacheNames.precache,
  }
);

// v5:
import {matchPrecache} from 'workbox-precaching';

const cachedResponse = await matchPrecache(`/somethingPrecached`);

Adoção do TypeScript

Na v5, as bibliotecas de ambiente de execução do Workbox são escritas em TypeScript. Vamos continuar publicando módulos e pacotes JavaScript transcompilados para atender aos desenvolvedores que não adotaram o TypeScript. No entanto, se você estiver usando o TypeScript, vai ter acesso a informações de tipo precisas e sempre atualizadas diretamente do projeto do Workbox.

Exemplo de migração

Esta confirmação ilustra que é uma migração bastante envolvida, com comentários inline. Ele usa o Rollup para incluir um ambiente de execução personalizado do Workbox no service worker final em vez de carregar o ambiente de execução pela CDN.

Embora não aborde todas as alterações interruptivas, veja a seguir o antes e o depois do upgrade de um arquivo do service worker da v4 para a v5, incluindo a mudança para o TypeScript.

Como buscar ajuda

Acreditamos que a maioria das migrações são simples. Se você tiver problemas não abordados neste guia, abra um problema no GitHub para nos informar.