Migrar do Workbox v5 para v6

Este guia se concentra nas alterações interruptivas introduzidas no Workbox v6, com exemplos de mudanças que você precisa fazer ao fazer upgrade do Workbox v5.

Alterações interruptivas

workbox-core

O método skipWaiting() em workbox-core não vai mais adicionar um gerenciador install e é equivalente a apenas chamar self.skipWaiting().

A partir de agora, use self.skipWaiting(), já que skipWaiting() provavelmente será removido na v7 do Workbox.

workbox-precaching

  • Os documentos HTML entre origens para URLs que correspondem a um redirecionamento HTTP não podem mais ser usados para atender a uma solicitação de navegação com workbox-precaching. Esse cenário geralmente é incomum.
  • O parâmetro de consulta de URL fbclid agora é ignorado pelo workbox-precaching ao procurar uma resposta pré-armazenada em cache para uma determinada solicitação.
  • O construtor PrecacheController agora usa um objeto com propriedades específicas como parâmetro, em vez de uma string. Esse objeto é compatível com as seguintes propriedades: cacheName (com a mesma finalidade da string transmitida ao construtor na v5), plugins (substituindo o método addPlugins() da v5) e fallbackToNetwork (substituindo a opção semelhante transmitida para createHandler() e "createHandlerBoundToURL()" na v5).
  • Os métodos install() e activate() de PrecacheController agora usam exatamente um parâmetro, que precisa ser definido como um InstallEvent ou ActivateEvent correspondente, respectivamente.
  • O método addRoute() foi removido de PrecacheController. Em vez disso, a nova classe PrecacheRoute pode ser usada para criar uma rota que pode ser registrada.
  • O método precacheAndRoute() foi removido de PrecacheController. Ele ainda existe como um método auxiliar estático exportado pelo módulo workbox-precaching. Ela foi removida porque PrecacheRoute pode ser usado no lugar.
  • O método createMatchCalback() foi removido de PrecacheController. O novo PrecacheRoute pode ser usado no lugar.
  • O método createHandler() foi removido de PrecacheController. A propriedade strategy do objeto PrecacheController pode ser usada para processar solicitações.
  • A exportação estática createHandler() já foi removida do módulo workbox-precaching. Em vez disso, os desenvolvedores precisam criar uma instância PrecacheController e usar a propriedade strategy dela.
  • A rota registrada com precacheAndRoute() agora é uma rota "real" que usa a classe Router do workbox-routing em segundo plano. Isso pode levar a uma ordem de avaliação diferente das suas rotas se você intercalar chamadas para registerRoute() e precacheAndRoute().

workbox-routing

O método setDefaultHandler() agora usa um segundo parâmetro opcional correspondente ao método HTTP ao qual ele se aplica, com o padrão 'GET'.

  • Se você usa setDefaultHandler() e todas as suas solicitações são GET, não é necessário fazer mudanças.
  • Se você tiver solicitações que não sejam GET (POST, PUT etc.), setDefaultHandler() não vai mais fazer com que essas solicitações correspondam.

Configuração do build

A opção mode para os modos getManifest e injectManifest em workbox-build e workbox-cli não deveria ser compatível e foi removida. Isso não se aplica ao workbox-webpack-plugin, que é compatível com o mode no plug-in InjectManifest.

As ferramentas de build exigem o Node.js v10 ou mais recente

As versões do Node.js anteriores à v10 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 à v8, atualize o ambiente de execução para uma versão compatível.

Novas melhorias

workbox-strategies

O Workbox v6 apresenta uma nova maneira para desenvolvedores terceirizados definirem as próprias estratégias do Workbox. Isso garante que os desenvolvedores de terceiros possam estender o Workbox de maneiras que atendam totalmente às necessidades deles.

Nova classe de base Strategy

Na v6, todas as classes de estratégia do Workbox precisam estender a nova classe de base Strategy. Todas as estratégias integradas foram reescritas para oferecer suporte a isso.

A classe de base Strategy é responsável por duas coisas principais:

  • Invocação de callbacks do ciclo de vida do plug-in comuns a todos os gerenciadores de estratégia (por exemplo, quando eles começam, respondem e terminam).
  • Criar uma instância de "gerenciador", que pode gerenciar o estado de cada solicitação individual que uma estratégia está processando.

Nova classe "handler"

Antes, os módulos internos chamavam fetchWrapper e cacheWrapper, que (como o nome indica) encapsulam as várias APIs de busca e cache com hooks no ciclo de vida delas. Esse é o mecanismo que permite que os plug-ins funcionem, mas ele não é exposto aos desenvolvedores.

A nova classe "handler", StrategyHandler, vai expor esses métodos para que as estratégias personalizadas possam chamar fetch() ou cacheMatch() e invocar automaticamente todos os plug-ins adicionados à instância da estratégia.

Essa classe também permitiria que os desenvolvedores adicionassem os próprios callbacks do ciclo de vida personalizados, que poderiam ser específicos para as estratégias deles, e eles "simplesmente funcionariam" com a interface de plug-in atual.

Novo estado do ciclo de vida do plug-in

No Workbox v5, os plug-ins não têm estado. Isso significa que, se uma solicitação de /index.html acionar os callbacks requestWillFetch e cachedResponseWillBeUsed, eles não poderão se comunicar entre si nem saber que foram acionados pela mesma solicitação.

Na v6, todos os callbacks de plug-in também vão receber um novo objeto state. Esse objeto de estado será exclusivo para esse objeto de plug-in específico e essa invocação de estratégia específica (ou seja, a chamada para handle()). Isso permite que os desenvolvedores criem plug-ins em que um callback pode fazer algo condicionalmente com base no que outro callback no mesmo plug-in fez (por exemplo, calcular o delta de tempo entre a execução de requestWillFetch e fetchDidSucceed ou fetchDidFail).

Novos callbacks do ciclo de vida do plug-in

Novos callbacks de ciclo de vida do plug-in foram adicionados para permitir que os desenvolvedores aproveitem ao máximo o estado do ciclo de vida do plug-in:

  • handlerWillStart: chamado antes que qualquer lógica de gerenciador comece a ser executada. Esse callback pode ser usado para definir o estado inicial do gerenciador (por exemplo, registrar o horário de início).
  • handlerWillRespond: chamado antes que o método handle() das estratégias retorne uma resposta. Esse callback pode ser usado para modificar essa resposta antes de retorná-la a um gerenciador de rotas ou outra lógica personalizada.
  • handlerDidRespond: chamado depois que o método handle() da estratégia retorna uma resposta. Esse callback pode ser usado para registrar detalhes da resposta final, por exemplo, após mudanças feitas por outros plug-ins.
  • handlerDidComplete: chamado depois que todas as promessas de extensão de ciclo de vida adicionadas ao evento pela invocação dessa estratégia forem resolvidas. Esse callback pode ser usado para informar dados que precisam aguardar até que o gerenciador seja concluído para serem calculados (por exemplo, status de ocorrência em cache, latência de cache, latência de rede).
  • handlerDidError: chamado se o gerenciador não conseguir fornecer uma resposta válida de qualquer origem. Esse callback pode ser usado para fornecer conteúdo de "substituição" como alternativa a um erro de rede.

Os desenvolvedores que implementam as próprias estratégias personalizadas não precisam se preocupar em invocar esses callbacks. Isso é feito por uma nova classe de base Strategy.

Tipos de TypeScript mais precisos para gerenciadores

As definições do TypeScript para vários métodos de callback foram normalizadas. Isso deve melhorar a experiência dos desenvolvedores que usam o TypeScript e escrevem o próprio código para implementar ou chamar gerenciadores.

workbox-window

Novo método messageSkipWaiting()

Um novo método, messageSkipWaiting(), foi adicionado ao módulo workbox-window para simplificar o processo de informar ao service worker "em espera" que ele deve ser ativado. Isso oferece algumas melhorias:

  • Ele chama postMessage() com o corpo da mensagem padrão de fato, {type: 'SKIP_WAITING'}, que um service worker gerado pelo Workbox verifica para acionar skipWaiting().
  • Ele escolhe o service worker "em espera" correto para postar essa mensagem, mesmo que não seja o mesmo service worker com que o workbox-window foi registrado.

Remoção de eventos "externos" em favor de uma propriedade isExternal

Todos os eventos "externos" em workbox-window foram removidos e substituídos por eventos "normais" com uma propriedade isExternal definida como true. Isso permite que os desenvolvedores que se importam com a distinção ainda a detectem, e os desenvolvedores que não precisam saber podem ignorar a propriedade.

Receita mais limpa de "Oferecer uma atualização de página para os usuários"

Graças às duas mudanças acima, a receita Oferecer uma atualização de página para os usuários pode ser simplificada:

// v6:
<script type="module">
  import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.0.0-alpha.1/workbox-window.prod.mjs';

  if ('serviceWorker' in navigator) {
    const wb = new Workbox('/sw.js');

    const showSkipWaitingPrompt = () => {
      // This assumes a hypothetical createUIPrompt() method with
      // onAccept and onReject callbacks:
      const prompt = createUIPrompt({
        onAccept: () => {
          wb.addEventListener('controlling', () => {
            window.location.reload();
          });

          // This will postMessage() to the waiting service worker.
          wb.messageSkipWaiting();
        },

        onReject: () => {
          prompt.dismiss();
        },
      });
    };

    // Listening for externalwaiting is no longer needed.
    wb.addEventListener('waiting', showSkipWaitingPrompt);
    wb.register();
  }
</script>

workbox-routing

Um novo parâmetro booleano, sameOrigin, é transmitido para a função matchCallback usada em workbox-routing. Ele será definido como true se a solicitação for para um URL de mesma origem e como falso, caso contrário.

Isso simplifica alguns códigos boilerplate comuns:

// In v5:
registerRoute(
  ({url}) =>
    url.origin === self.location.origin && url.pathname.endsWith('.png'),
  new StaleWhileRevalidate({cacheName: 'local-png'})
);

// In v6:
registerRoute(
  ({sameOrigin, url}) => sameOrigin && url.pathname.endsWith('.png'),
  new StaleWhileRevalidate({cacheName: 'local-png'})
);

matchOptions em workbox-expiration

Agora é possível definir matchOptions em workbox-expiration, que será transmitido como CacheQueryOptions para a chamada cache.delete(). A maioria dos desenvolvedores não precisa fazer isso.

workbox-precaching

Usa workbox-strategies

workbox-precaching foi reescrito para usar workbox-strategies como base. Isso não deve resultar em alterações interruptivas e deve levar a uma melhor consistência de longo prazo na forma como os dois módulos acessam a rede e o cache.

O pré-armazenamento em cache agora processa as entradas uma por uma, não em massa

O workbox-precaching foi atualizado para que apenas uma entrada no manifesto de pré-armazenamento em cache seja solicitada e armazenada em cache por vez, em vez de tentar solicitar e armazenar em cache todas de uma vez (deixando para o navegador descobrir como limitar).

Isso reduz a probabilidade de erros net::ERR_INSUFFICIENT_RESOURCES durante o pré-armazenamento em cache e também a contenção de largura de banda entre o pré-armazenamento em cache e as solicitações simultâneas feitas pelo app da Web.

O PrecacheFallbackPlugin facilita o substituto off-line

workbox-precaching agora inclui um PrecacheFallbackPlugin, que implementa o novo método de ciclo de vida handlerDidError adicionado na v6.

Isso facilita a especificação de um URL pré-armazenado em cache como um "substituto" para uma determinada estratégia quando uma resposta não está disponível. O plug-in vai criar corretamente a chave de cache certa para o URL pré-armazenado em cache, incluindo qualquer parâmetro de revisão necessário.

Veja um exemplo de como usá-lo para responder com um /offline.html pré-armazenado em cache quando a estratégia NetworkOnly não pode gerar uma resposta para uma solicitação de navegação, ou seja, exibir uma página HTML off-line personalizada:

import {PrecacheFallbackPlugin, precacheAndRoute} from 'workbox-precaching';
import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

// Ensure that /offline.html is part of your precache manifest!
precacheAndRoute(self.__WB_MANIFEST);

registerRoute(
  ({request}) => request.mode === 'navigate',
  new NetworkOnly({
    plugins: [
      new PrecacheFallbackPlugin({
        fallbackURL: '/offline.html',
      }),
    ],
  })
);

precacheFallback no armazenamento em cache do ambiente de execução

Se você estiver usando o generateSW para criar um service worker em vez de escrever um manualmente, use a nova opção de configuração precacheFallback em runtimeCaching para fazer o mesmo:

{
  // ... other generateSW config options...
  runtimeCaching: [{
    urlPattern: ({request}) => request.mode === 'navigate',
    handler: 'NetworkOnly',
    options: {
      precacheFallback: {
        // This URL needs to be included in your precache manifest.
        fallbackURL: '/offline.html',
      },
    },
  }],
}

Como receber ajuda

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