Como usar o workbox-window

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.