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
.
Mudanças no trajeto de navegação
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:
- Detectado se um determinado evento
fetch
tinha ou não ummode
de'navigate'
. - 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.