Um módulo do Workbox que ainda não foi abordado nesta documentação é o workbox-window
, que é um conjunto de módulos destinados à execução em window
. Os objetivos deste módulo são:
- Simplificar o registro e as atualizações do service worker, ajudando os desenvolvedores a identificar momentos críticos do ciclo de vida do service worker, facilitando a resposta a eles.
- Para evitar que os desenvolvedores cometam erros comuns, como registrar um service worker no escopo errado.
- Para simplificar a troca de mensagens entre o
window
e o escopo do service worker.
Como importar e usar workbox-window
A exportação que você vai usar com mais frequência de workbox-window
é a classe Workbox
, que pode ser importada no Node ou da CDN em uma página da Web.
Como criar um pacote local
Se o conjunto de ferramentas incluir um bundler como webpack ou Rollup, você pode agrupar workbox-window
localmente.
Primeiro, instale workbox-window
como uma dependência de produção do seu aplicativo:
npm install workbox-window --save
Em seguida, no JavaScript do aplicativo, você pode usar import
na classe Workbox
de workbox-window
:
<script type="module">
import {Workbox} from 'workbox-window';
if ('serviceWorker' in navigator) {
const wb = new Workbox('/sw.js');
wb.register();
}
</script>
Embora o workbox-window
seja bem pequeno, é possível dividi-lo da lógica principal do aplicativo do seu site usando o import
dinâmico, que pode reduzir o tamanho do pacote principal da página:
<script type="module">
if ('serviceWorker' in navigator) {
const {Workbox} = await import('workbox-window');
const wb = new Workbox('/sw.js');
wb.register();
}
</script>
Como usar a CDN
Embora não seja a abordagem recomendada, uma maneira mais fácil de usar o workbox-window
é importá-lo de uma CDN:
<script type="module">
import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.2.0/workbox-window.prod.mjs';
if ('serviceWorker' in navigator) {
const wb = new Workbox('/sw.js');
wb.register();
}
</script>
Observe que o elemento <script>
no exemplo acima usa o atributo type="module"
. Isso é necessário se você quer usar instruções import
estáticas no navegador sem uma etapa de build. Todos os principais navegadores com suporte a service workers também oferecem suporte a módulos JavaScript. Portanto, não há problema em disponibilizar esse código em qualquer navegador, já que navegadores mais antigos ignorarão elementos <script>
com um valor de atributo type
de "module"
.
Como registrar um service worker
O registro de um service worker com workbox-window
é feito com o método register
da classe Workbox
, da seguinte maneira:
import {Workbox} from 'workbox-window';
const wb = new Workbox('/sw.js');
wb.register();
Pode parecer que isso é o mesmo que registrar um service worker usando navigator.serviceWorker.register
. No entanto, o Workbox.register
se encarrega de aguardar até o evento window
load
antes de registrar o service worker. Isso é útil em situações em que o armazenamento em cache está envolvido para evitar a contenção da largura de banda, que pode atrasar a inicialização da página.
Comunicação entre o window
e o escopo do service worker
Os service workers têm o próprio escopo separado do window
e têm acesso apenas a um subconjunto das APIs disponíveis no window
. No entanto, é possível estabelecer comunicação entre o window
e o service worker. workbox-window
facilita a comunicação entre os dois escopos com o método messageSW
do módulo workbox-window
.
O Workbox usa um formato específico para mensagens é um objeto com as seguintes propriedades:
type
é uma string exclusiva obrigatória que identifica a mensagem. O formato deve estar em maiúsculas com sublinhados separando palavras (por exemplo,CACHE_URLS
).meta
é uma string opcional que representa o nome do pacote do Workbox que envia a mensagem e geralmente é omitida.payload
é um parâmetro opcional que representa os dados que você quer enviar. Pode ser qualquer tipo de dado.
Veja abaixo um exemplo de como messageSW
funciona, começando com o código no service worker:
// sw.js
const SW_VERSION = '1.0.0';
self.addEventListener('message', (event) => {
if (event.data.type === 'GET_VERSION') {
event.ports[0].postMessage(SW_VERSION);
}
});
E o seguinte código na sua página da Web:
const wb = new Workbox('/sw.js');
wb.register();
const swVersion = await wb.messageSW({type: 'GET_VERSION'});
console.log('Service Worker version:', swVersion);
Há muitas instâncias em que a comunicação entre um service worker e o window
pode ser útil, como notificar o usuário quando uma atualização de service worker está disponível. Essa receita depende de um método auxiliar especial para self.skipWaiting
chamado messageSkipWaiting
, que envia uma mensagem com um valor type
de SKIP_WAITING
.