Service Workers

Os usuários esperam que os apps sejam iniciados em conexões de rede lentas ou instáveis ou até mesmo off-line. Ele espera que o conteúdo com que interagiu mais recentemente, como faixas de mídia ou ingressos e itinerários, esteja disponível e usável. Quando uma solicitação não é possível, eles esperam que o app informe, em vez de falhar ou falhar silenciosamente. E os usuários querem fazer tudo isso rapidamente. Como podemos observar neste estudo, Milissegundos geram milhões, mesmo uma melhoria de 0,1 segundo nos tempos de carregamento pode melhorar a conversão em até 10%. Em resumo: os usuários esperam que os PWAs sejam confiáveis, e é por isso que temos service workers.

Hello Service workers

Um service worker como proxy de middleware, executado no lado do dispositivo, entre o PWA e os servidores, o que inclui seus próprios servidores e servidores de vários domínios.

Quando um app solicita um recurso coberto pelo escopo do service worker, inclusive quando um usuário está off-line, o service worker intercepta a solicitação, atuando como um proxy de rede. Assim, ele pode decidir se deve disponibilizar o recurso do cache por meio da API Cache Storage, da rede, como aconteceria normalmente sem um service worker, ou criá-lo a partir de um algoritmo local. Isso permite que você ofereça uma experiência semelhante à oferecida por um app de plataforma. Ele pode até funcionar totalmente off-line.

Como registrar um service worker

Antes que um service worker assuma o controle da sua página, ela precisa ser registrada para seu PWA. Isso significa que, na primeira vez que um usuário acessar seu PWA, as solicitações de rede vão diretamente para seu servidor porque o service worker ainda não está no controle das suas páginas.

Depois de verificar se o navegador é compatível com a API Service Worker, o PWA poderá registrar um service worker. Quando carregado, o service worker configura a loja entre o PWA e a rede, interceptando solicitações e exibindo as respostas correspondentes.

if ('serviceWorker' in navigator) {
   navigator.serviceWorker.register("/serviceworker.js");
}

Verificar se um service worker está registrado

Para verificar se um service worker está registrado, use as ferramentas para desenvolvedores no seu navegador favorito.

Em navegadores baseados no Firefox e no Chromium (Microsoft Edge, Google Chrome ou Samsung Internet):

  1. Abra as ferramentas de desenvolvedor e clique na guia Aplicativo.
  2. No painel esquerdo, selecione Service Workers.
  3. Verifique se o URL do script do service worker aparece com o status "Ativado". Você vai aprender o que esse status significa na seção do ciclo de vida deste capítulo. No Firefox, o status pode ser "Em execução" ou "Interrompido".

No Safari:

  1. Clique no menu Develop e no submenu Service Workers.
  2. Verifique se uma entrada com a origem atual aparece no submenu. Isso abre um inspetor sobre o contexto do service worker.
Ferramentas para desenvolvedores de service worker no Chrome, Firefox e Safari.
Ferramentas para desenvolvedores de service worker no Chrome, Firefox e Safari.

Escopo

A pasta em que o service worker está localizado determina o escopo. Um service worker que reside em example.com/my-pwa/sw.js pode controlar qualquer navegação no caminho my-pwa ou abaixo, como example.com/my-pwa/demos/. Os service workers só podem controlar itens (páginas, workers, coletivamente "clientes") em seu escopo. O escopo se aplica às guias do navegador e às janelas do PWA.

É permitido apenas um service worker por escopo. Quando ativa e em execução, normalmente apenas uma instância fica disponível, não importa quantos clientes estejam na memória (como janelas de PWA ou guias do navegador).

O Safari tem gerenciamento de escopo mais complexo, conhecido como partições, que afeta o funcionamento dos escopos se você tiver iframes entre domínios. Para ler mais sobre a implementação do WebKit, leia a postagem do blog (link em inglês).

Lifecycle

Os service workers têm um ciclo de vida que determina como eles são instalados. Isso é separado da instalação do PWA. O ciclo de vida do service worker começa com o registro dele. Em seguida, o navegador tenta fazer o download e analisar o arquivo do service worker. Se a análise for bem-sucedida, o evento install será disparado. O evento install é disparado apenas uma vez.

A instalação do service worker acontece silenciosamente, sem precisar da permissão do usuário, mesmo que ele não instale o PWA. A API Service Worker está disponível até em plataformas que não oferecem suporte à instalação de PWA, como Safari e Firefox em dispositivos desktop.

Após a instalação, o service worker ainda não estará no controle dos clientes, incluindo o PWA. Ele precisa ser ativado primeiro. Quando o service worker estiver pronto para controlar os clientes, o evento activate será disparado. No entanto, isso não significa que a página que registrou o service worker será gerenciada. Por padrão, o service worker não assumirá o controle até a próxima vez que você acessar essa página, seja para atualizar a página ou reabrir o PWA.

É possível detectar eventos no escopo global do service worker usando o objeto self.

serviceworker.js

// This code executes in its own worker or thread
self.addEventListener("install", event => {
   console.log("Service worker installed");
});
self.addEventListener("activate", event => {
   console.log("Service worker activated");
});

Como atualizar um service worker

Os service workers são atualizados quando o navegador detecta que o service worker que está controlando o cliente atualmente e a nova versão (do seu servidor) do mesmo arquivo têm byte diferente.

Após uma instalação bem-sucedida, o novo service worker esperará para ativar até que o existente (antigo) não controle mais nenhum cliente. Esse estado é chamado de "espera" e é como o navegador garante que apenas uma versão do service worker seja executada por vez. Atualizar uma página ou reabrir o PWA não fará com que o novo service worker assuma o controle. O usuário precisa fechar ou sair de todas as guias e janelas usando o service worker atual e, em seguida, navegar de volta. Só assim o novo service worker assumirá o controle. Acesse este artigo sobre o ciclo de vida do service worker para mais informações.

Vida útil do service worker

Depois de instalado e registrado, o service worker pode gerenciar todas as solicitações de rede dentro do seu escopo. Ela é executada na própria linha de execução, com ativação e encerramento controladas pelo navegador. Isso permite que ele funcione mesmo antes ou depois de o PWA ser aberto. Embora os service workers sejam executados na própria linha de execução, não há garantia de que o estado na memória vai persistir entre as execuções de um service worker. Por isso, confira se tudo que você quer reutilizar em cada execução está disponível no IndexedDB ou em outro armazenamento permanente.

Se ainda não estiver em execução, um service worker será iniciado sempre que uma solicitação de rede no escopo for solicitada ou quando um evento de acionamento, como uma sincronização periódica em segundo plano ou uma mensagem de push, for recebido.

Os service workers não ficam armazenados indefinidamente. Embora os horários exatos sejam diferentes entre os navegadores, os service workers serão encerrados se ficarem inativos por alguns segundos ou ocupados por muito tempo. Se um service worker tiver sido encerrado e ocorrer um evento que o inicie, ele será reiniciado.

Recursos

Com um service worker registrado e ativo, você tem uma linha de execução com um ciclo de execução completamente diferente do que a principal do PWA. No entanto, por padrão, o próprio arquivo do service worker não tem comportamento. Ele não vai armazenar em cache nem disponibilizar recursos, já que isso precisa ser feito pelo seu código. Você descobrirá como nos próximos capítulos.

Os recursos do service worker não se destinam apenas a solicitações HTTP ou de proxy. Outros recursos também estão disponíveis para outras finalidades, como execução de código em segundo plano, notificações push da Web e pagamentos de processos. Vamos falar sobre essas adições no capítulo de recursos.

Recursos