Práticas recomendadas para programar o registro do service worker.
Os service workers podem acelerar significativamente as visitas repetidas ao seu app da Web, mas você precisa tomar medidas para garantir que a instalação inicial de um service worker não prejudique a experiência do primeiro acesso do usuário.
Geralmente, adiar o registro do service worker até que a página inicial seja carregada para oferecer a melhor experiência para os usuários, especialmente aqueles em dispositivos móveis com conexões de rede mais lentas.
Código de registro comum
Se você já leu sobre service workers, provavelmente se deparou com boilerplate semelhante ao seguinte:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js');
}
Às vezes, isso pode ser acompanhado por algumas instruções console.log()
ou
código
que detecta uma atualização no registro de um service worker anterior, como uma forma de
permitir que os usuários atualizem a página. Mas essas são pequenas variações
nas poucas linhas de código padrão.
Há alguma nuance em navigator.serviceWorker.register
? Há alguma prática
recomendada a seguir? Não surpreende que a resposta para as duas coisas seja "sim", já que este artigo não termina aqui.
A primeira visita do usuário
Vamos considerar a primeira visita de um usuário a um app da Web. Ainda não há service worker, e o navegador não tem como saber com antecedência se um service worker será instalado.
Como desenvolvedor, sua prioridade precisa ser garantir que o navegador receba rapidamente o conjunto mínimo de recursos críticos necessários para exibir uma página interativa. Qualquer coisa que atrasa a recuperação dessas respostas é inimigo de uma experiência rápida de interação.
Agora, imagine que, no processo de download do JavaScript ou das imagens que a página precisa para renderizar, o navegador decida iniciar uma linha de execução ou um processo em segundo plano (para simplificar, vamos presumir que é uma linha de execução). Suponha que você não esteja usando um computador superpoderoso, mas sim o tipo de smartphone menos potente que grande parte do mundo considera como o dispositivo principal. Ativar essa linha de execução extra aumenta a contenção do tempo de CPU e da memória que o navegador poderia gastar na renderização de uma página da Web interativa.
É improvável que uma linha de execução ociosa em segundo plano faça uma diferença significativa. Mas e se essa linha de execução não estiver inativa, mas decidir que também vai começar o download de recursos da rede? Qualquer preocupação com a contenção de CPU ou memória ficará abandonada por questões da largura de banda limitada disponível para muitos dispositivos móveis. A largura de banda é algo precioso, por isso, não atrapalhe os recursos críticos fazendo o download de recursos secundários ao mesmo tempo.
Tudo isso para dizer que ativar uma nova linha de execução de service worker para fazer o download e armazenar recursos em cache em segundo plano pode prejudicar seu objetivo de fornecer a experiência de interação mais curta na primeira vez que um usuário visitar seu site.
Como melhorar o boilerplate
A solução é controlar o início do service worker escolhendo quando chamar
navigator.serviceWorker.register()
. Uma regra prática simples é atrasar
o registro até que load
event
seja disparado em window
, desta forma:
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/service-worker.js');
});
}
No entanto, o momento certo para iniciar o registro do service worker também pode depender do que seu app da Web está fazendo logo após o carregamento. Por exemplo, o app da Web do Google I/O 2016 apresenta uma pequena animação antes de fazer a transição para a tela principal. Nossa equipe descobriu que iniciar o registro do service worker durante a animação pode levar à instabilidade em dispositivos móveis mais simples. Em vez de oferecer aos usuários uma experiência ruim, atrasamos o registro do service worker até depois da animação, quando o navegador provavelmente teria alguns segundos de inatividade.
Da mesma forma, se o app da Web usar um framework que faz outras configurações após o carregamento da página, procure um evento específico do framework que indique quando esse trabalho for concluído.
Visitas subsequentes
Estamos nos concentrando na experiência de primeira visita até agora, mas qual é o impacto do registro atrasado do service worker em visitas repetidas ao seu site? Embora isso possa surpreender algumas pessoas, não haverá nenhum impacto.
Quando um service worker é registrado, ele passa pelos eventos de ciclo de vida
install
e
activate
.
Depois que um service worker é ativado, ele pode processar eventos fetch
para todas
as visitas subsequentes ao seu app da Web. O service worker começa antes de a
solicitação de qualquer página no escopo dele ser feita, o que faz sentido quando você
pensa sobre isso. Se o service worker já não estiver em execução antes de
acessar uma página, ele não vai conseguir atender a eventos fetch
para
solicitações de navegação.
Portanto, quando há um service worker ativo, não importa quando você chama
navigator.serviceWorker.register()
ou, se você o chama.
A menos que você altere o URL do script do service worker, navigator.serviceWorker.register()
será um ambiente autônomo durante as visitas subsequentes. O momento da chamada é irrelevante.
Motivos para registrar com antecedência
Há algum cenário em que registrar o service worker o quanto
antes é adequado? Uma que vem à mente é quando o service worker usa
clients.claim()
para assumir o controle da página durante a primeira visita e quando executa o armazenamento em cache
no ambiente de execução
de forma agressiva dentro do gerenciador fetch
. Nessa situação, há uma
vantagem em ativar o service worker o mais rápido possível, para tentar
preencher os caches de ambiente de execução com recursos que podem ser úteis mais tarde. Caso
seu app da Web se enquadre nessa categoria, vale a pena dar um passo atrás para garantir
que o gerenciador install
do service worker não solicite
recursos que briguem por largura de banda com as solicitações da página principal.
Fazendo testes
Uma ótima maneira de simular um primeiro acesso é abrir o app da Web em uma janela anônima do Chrome e observar o tráfego de rede no DevTools do Chrome. Como desenvolvedor da Web, você provavelmente recarrega uma instância local do seu app da Web dezenas e dezenas de vezes por dia. No entanto, ao acessar seu site novamente quando já houver um service worker e caches totalmente preenchidos, você não terá a mesma experiência que um novo usuário teria, e é fácil ignorar um possível problema.
Este é um exemplo que ilustra a diferença que o momento do registro pode fazer. As duas capturas de tela foram feitas ao visitar um app de exemplo no modo de navegação anônima usando a limitação de rede para simular uma conexão lenta.
A captura de tela acima reflete o tráfego de rede quando a amostra foi modificada para executar o registro do service worker o mais rápido possível. É possível ver as solicitações de pré-armazenamento em cache (as entradas com o ícone de engrenagem ao lado delas, originadas do gerenciador install
do service worker) intercaladas com solicitações para os outros recursos necessários para exibir a página.
Na captura de tela acima, o registro do service worker foi adiado até que a página fosse carregada. As solicitações de pré-armazenamento em cache não são iniciadas até que todos
os recursos tenham sido buscados na rede, eliminando qualquer contenção da
largura de banda. Além disso, como alguns dos itens que estamos pré-armazenando em cache já estão no
cache HTTP do navegador (os itens com (from disk cache)
na coluna Tamanho),
podemos preencher o cache do service worker sem ter que acessar a
rede novamente.
Pontos extras se você executar esse tipo de teste em um dispositivo real e mais simples em uma rede móvel real. Você pode aproveitar os recursos de depuração remota do Chrome para conectar um smartphone Android à sua máquina desktop via USB e garantir que os testes executados realmente reflitam a experiência real de muitos dos seus usuários.
Conclusão
Para resumir, garantir que os usuários tenham a melhor experiência no primeiro acesso é a prioridade. Adiar o registro do service worker até que a página seja carregada durante a visita inicial pode ajudar a garantir isso. Você ainda terá todos os benefícios de um service worker nas visitas repetidas.
Uma maneira simples de garantir o atraso do registro inicial do seu service worker até que a primeira página seja carregada é usar o seguinte:
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/service-worker.js');
});
}