Como trabalhar com service workers

Este codelab mostra como registrar um service worker no seu aplicativo da Web e usar o Chrome DevTools para observar o comportamento dele. Ele também aborda algumas técnicas de depuração que podem ser úteis ao lidar com service workers.

Conhecer o projeto de exemplo

Os arquivos do projeto de exemplo mais relevantes para este codelab são:

  • register-sw.js começa vazio, mas vai conter o código usado para registrar o service worker. Ele já está sendo carregado por uma tag <script> dentro do index.html do projeto.
  • service-worker.js também está vazio. É o arquivo que vai conter o worker de serviço para esse projeto.

Adicionar o código de registro do service worker

Um worker de serviço (mesmo que vazio, como o arquivo service-worker.js atual) não será usado a menos que seja registrado. Para fazer isso, chame:

navigator.serviceWorker.register(
  '/service-worker.js'
)

no arquivo register-sw.js.

No entanto, antes de adicionar esse código, há alguns pontos a serem considerados.

Primeiro, nem todos os navegadores oferecem suporte a service workers. Isso é especialmente verdadeiro para versões mais antigas de navegadores que não são atualizadas automaticamente. Portanto, é uma prática recomendada chamar navigator.serviceWorker.register() condicionalmente, depois de verificar se navigator.serviceWorker tem suporte.

Em segundo lugar, quando você registra um worker de serviço, o navegador executa o código no arquivo service-worker.js e pode começar a fazer o download de URLs para preencher caches, dependendo do código nos manipuladores de eventos install e activate do worker de serviço.

A execução de códigos adicionais e o download de recursos podem usar recursos valiosos que o navegador poderia usar para mostrar a página da Web atual. Para evitar essa interferência, é recomendável atrasar o registro de um service worker até que o navegador termine de renderizar a página atual. Uma maneira conveniente de aproximar isso é esperar até que o evento window.load seja acionado.

Juntando esses dois pontos, adicione este código de registro de worker de serviço de finalidade geral ao arquivo register-sw.js:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js');
  });
}

Adicionar um código de registro de service worker

O arquivo service-worker.js é onde toda a lógica da implementação do service worker normalmente fica. Você usaria uma mistura dos eventos de ciclo de vida, a API Cache Storage e o conhecimento sobre o tráfego de rede do seu app da Web para criar um service worker perfeitamente criado, pronto para processar todas as solicitações do app da Web.

Mas… isso é tudo para aprender mais tarde. Nesta etapa, o foco é observar vários eventos de service worker e se familiarizar com o uso do Chrome DevTools para depurar o estado do service worker.

Para isso, adicione o código abaixo a service-worker.js, que vai registrar mensagens no console do DevTools em resposta a vários eventos (mas não muito mais):

self.addEventListener('install', (event) => {
  console.log('Inside the install handler:', event);
});

self.addEventListener('activate', (event) => {
  console.log('Inside the activate handler:', event);
});

self.addEventListener(fetch, (event) => {
  console.log('Inside the fetch handler:', event);
});

Conheça o painel "Service Workers" no DevTools

Agora que você adicionou o código aos arquivos register-sw.js e service-worker.js, é hora de acessar a versão ativa do seu projeto de exemplo e observar o service worker em ação.

  • Para visualizar o site, pressione View App. Em seguida, pressione Fullscreen tela cheia.
  • Pressione "Control+Shift+J" (ou "Command+Option+J" no Mac) para abrir as Ferramentas do desenvolvedor.
  • Clique na guia Console.

Você verá mensagens de registro semelhantes às seguintes, mostrando que o service worker foi instalado e ativado:

Mostra que o service worker está instalado e ativado.

Em seguida, acesse a guia Aplicativos e selecione o painel Service Workers. Será exibido um resultado parecido com este:

Mostra detalhes do worker de serviço no painel do worker de serviço.

Isso informa que há um service worker com um URL de origem de service-worker.js, para o app da Web solar-donkey.glitch.me, que está atualmente ativado e em execução. Ele também informa que atualmente há um cliente (aba aberta) que está sendo controlado pelo service worker.

É possível usar os links nesse painel, como Unregister ou stop, para fazer alterações no service worker registrado no momento para fins de depuração.

Acionar o fluxo de atualização do worker de serviço

Um dos principais conceitos a serem compreendidos ao desenvolver com service workers é a ideia de um fluxo de atualização.

Depois que os usuários visitarem um app da Web que registra um worker de serviço, eles vão receber o código da cópia atual de service-worker.js instalada no navegador local. Mas o que acontece quando você faz atualizações na versão de service-worker.js armazenada no servidor da Web?

Quando um visitante recorrente retorna a um URL que está no escopo de um worker de serviço, o navegador solicita automaticamente a service-worker.js mais recente e verifica se há mudanças. Se algo no script do service worker for diferente, o novo service worker vai ter a chance de instalar, ativar e, eventualmente, assumir o controle.

Para simular esse fluxo de atualização, volte ao editor de código do seu projeto e faça qualquer mudança no código. Uma mudança rápida seria substituir

self.addEventListener('install', (event) => {
  console.log('Inside the install handler:', event);
});

com

self.addEventListener('install', (event) => {
  console.log('Inside the UPDATED install handler:', event);
});

Depois de fazer essa mudança, volte para a versão ativa do app de exemplo e recarregue a página com a guia "Application" do DevTools ainda aberta. Você vai ver algo como o seguinte:

Mostra duas versões do service worker instaladas.

Isso mostra que há duas versões do service worker instaladas neste momento. A versão anterior, que já estava ativada, está em execução e no controle da página atual. A versão atualizada do worker de serviço está listada logo abaixo. Ele está no estado waiting e vai permanecer aguardando até que todas as guias abertas controladas pelo service worker antigo sejam fechadas.

Esse comportamento padrão garante que, se o novo service worker tiver uma diferença fundamental no comportamento em relação ao antigo, como um gerenciador fetch que responde com recursos incompatíveis com versões mais antigas do app da Web, ele não vai entrar em vigor até que um usuário desligue todas as instâncias anteriores do app da Web.

Resumindo

Agora você já deve estar familiarizado com o processo de registro de um service worker e de observação do comportamento dele usando o Chrome DevTools.

Agora você está em uma boa posição para começar a implementar estratégias de armazenamento em cache e todas as coisas boas que ajudarão seu app da Web a carregar de forma confiável e rápida.