Como usar o workbox-window

Um módulo do Workbox que ainda não foi muito abordado nesta documentação é o workbox-window, que é um conjunto de módulos destinados a ser executado no window. Os objetivos deste módulo são:

  • Simplificar o registro e as atualizações de service workers ajudando os desenvolvedores a identificar momentos críticos do ciclo de vida de service workers, facilitando a resposta a esses momentos.
  • Para evitar que os desenvolvedores cometam erros comuns, como registrar um worker de serviço no escopo errado.
  • Para simplificar a mensagem entre o window e o escopo do service worker.

Importar e usar workbox-window

A exportação que você vai usar com mais frequência do workbox-window é a classe Workbox, que pode ser importada no nó ou do CDN em uma página da Web.

Como criar um pacote local

Se a cadeia de ferramentas incluir um bundler como webpack ou Rollup, será possível 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 import a 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 workbox-window seja bastante pequeno, você pode dividi-lo da lógica de aplicativo principal do seu site usando import dinâmico, o 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>

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 compatíveis com service workers também são compatíveis com módulos JavaScript, então 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, desta forma:

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, Workbox.register aguarda até o evento window load antes de registrar o worker de serviço. Isso é desejável em situações em que o pré-armazenamento em cache está envolvido, para evitar a contenção de largura de banda que pode atrasar a inicialização da página.

Como estabelecer comunicação entre o window e o escopo do service worker

Os service workers têm um 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 a 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, que é um objeto com as seguintes propriedades:

  • type é uma string exclusiva obrigatória que identifica a mensagem. O formato precisa ser em letras maiúsculas com sublinhados separando as palavras (por exemplo, CACHE_URLS).
  • meta é uma string opcional que representa o nome do pacote do Workbox que está enviando a mensagem e geralmente é omitida.
  • payload é um parâmetro opcional que representa os dados que você quer enviar. Pode ser qualquer tipo de dados.

Veja abaixo um exemplo de como messageSW funciona, começando com o código no seu 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);
  }
});

Depois, use 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á muitos casos em que a comunicação entre um service worker e o window pode ser útil, como notificar o usuário quando uma atualização do 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.