Texto longo, leia o resumo
A partir do Chrome 68, as solicitações HTTP que verificam se há atualizações no script do service worker não serão
mais atendidas pelo cache HTTP
por padrão. Isso funciona em torno de um problema comum para desenvolvedores,
em que a configuração de um cabeçalho Cache-Control
inadvertidamente no script do service worker pode levar
a atualizações atrasadas.
Se você já desativou o armazenamento em cache HTTP do script /service-worker.js
com Cache-Control: max-age=0
, não vai notar nenhuma mudança devido ao novo comportamento
padrão.
Além disso, a partir do Chrome 78, a comparação byte por byte será
aplicada aos scripts carregados em um service worker por meio de
importScripts()
.
Qualquer mudança feita em um script importado aciona o
fluxo de atualização do service worker,
assim como uma mudança no service worker de nível superior.
Contexto
Sempre que você navega para uma nova página que está no escopo de um service worker, chame explicitamente registration.update()
do JavaScript ou quando um service worker é "ativado" por um evento push
ou sync
. O navegador
vai, em paralelo, solicitar o recurso JavaScript que foi originalmente transmitido para a
chamada navigator.serviceWorker.register()
para procurar atualizações no script do service worker.
Para os fins deste artigo, vamos supor que o URL seja /service-worker.js
e que
ele contenha uma única chamada para importScripts()
,
que carrega um código adicional executado dentro do worker de serviço:
// Inside our /service-worker.js file:
importScripts('path/to/import.js');
// Other top-level code goes here.
O que muda?
Antes do Chrome 68, a solicitação de atualização para /service-worker.js
era feita pelo cache HTTP,
assim como a maioria das buscas. Isso significa que, se o script for enviado originalmente com Cache-Control:
max-age=600
, as atualizações nos próximos 600 segundos (10 minutos) não serão enviadas para a rede. Portanto, o
usuário pode não receber a versão mais atualizada do worker de serviço. No entanto, se max-age
fosse
maior que 86400 (24 horas), seria tratado como se fosse 86400, para evitar que os usuários ficassem
presos a uma versão específica para sempre.
A partir da versão 68, o cache HTTP será ignorado ao solicitar atualizações do script do service worker.
Portanto, os aplicativos da Web atuais podem apresentar um aumento na frequência de solicitações do
script do service worker. As solicitações de importScripts
ainda vão passar pelo cache HTTP. Mas esse é
apenas o padrão. Uma nova opção de registro, updateViaCache
, está disponível e oferece controle sobre
esse comportamento.
updateViaCache
Agora os desenvolvedores podem transmitir uma nova opção ao chamar navigator.serviceWorker.register()
: o parâmetro updateViaCache
.
Ele usa um dos três valores: 'imports'
, 'all'
ou 'none'
.
Os valores determinam se e como o cache HTTP padrão do navegador entra em ação ao fazer a solicitação HTTP para verificar se há recursos atualizados do service worker.
Quando definido como
'imports'
, o cache HTTP nunca será consultado ao verificar atualizações do script/service-worker.js
, mas será consultado ao buscar scripts importados (path/to/import.js
, no nosso exemplo). Esse é o padrão e corresponde ao comportamento a partir do Chrome 68.Quando definido como
'all'
, o cache HTTP será consultado ao fazer solicitações para o script/service-worker.js
de nível superior, bem como para todos os scripts importados no worker do serviço, comopath/to/import.js
. Essa opção corresponde ao comportamento anterior no Chrome, anterior ao Chrome 68.Quando definido como
'none'
, o cache HTTP não será consultado ao fazer solicitações para o/service-worker.js
de nível superior ou para scripts importados, como opath/to/import.js
hipotético.
Por exemplo, o código a seguir vai registrar um service worker e garantir que o cache HTTP nunca seja
consultado ao verificar atualizações no script /service-worker.js
ou em qualquer
script referenciado por importScripts()
dentro de /service-worker.js
:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js', {
updateViaCache: 'none',
// Optionally, set 'scope' here, if needed.
});
}
Verifica se há atualizações nos scripts importados
Antes do Chrome 78, qualquer script de service worker carregado pelo
importScripts()
era recuperado apenas uma vez (verificando primeiro no cache HTTP ou pela
rede, dependendo da configuração da updateViaCache
). Após essa recuperação
inicial, ele seria armazenado internamente pelo navegador e nunca seria buscado novamente.
A única maneira de forçar um service worker já instalado a detectar mudanças em
um script importado era mudar o URL do script, geralmente adicionando um
valor semver (por exemplo,
importScripts('https://example.com/v1.1.0/index.js')
) ou incluindo um hash do
conteúdo (por exemplo, importScripts('https://example.com/index.abcd1234.js')
). Um
efeito colateral da mudança do URL importado é que o conteúdo do script do service worker
de nível superior muda, o que, por sua vez, aciona o
fluxo de atualização do service worker.
A partir do Chrome 78, sempre que uma verificação de atualização for realizada para um arquivo de worker de serviço
de nível superior, as verificações serão feitas ao mesmo tempo para determinar se
o conteúdo de todos os scripts importados mudou ou não. Dependendo dos
cabeçalhos Cache-Control
usados, essas verificações de script importadas podem ser atendidas pelo
cache HTTP se updateViaCache
estiver definido como 'all'
ou 'imports'
(que é
o valor padrão), ou podem ser enviadas diretamente à rede se
updateViaCache
estiver definido como 'none'
.
Se uma verificação de atualização de um script importado resultar em uma diferença de byte para byte em comparação com o que foi armazenado anteriormente pelo service worker, isso vai acionar o fluxo de atualização completo do service worker, mesmo que o arquivo de service worker de nível superior continue o mesmo.
O comportamento do Chrome 78 corresponde ao que o Firefox implementou há vários anos, no Firefox 56. O Safari já implementa esse comportamento.
O que os desenvolvedores precisam fazer?
Se você tiver desativado o armazenamento em cache HTTP do script /service-worker.js
usando Cache-Control: max-age=0
(ou um valor semelhante), não vai notar nenhuma mudança devido ao novo comportamento padrão.
Se você enviar o script /service-worker.js
com o armazenamento em cache HTTP ativado, intencionalmente
ou porque é o padrão do seu ambiente de hospedagem,
pode começar a notar um aumento nas solicitações HTTP adicionais de /service-worker.js
feitas no
seu servidor, que costumavam ser atendidas pelo cache HTTP. Se você quiser
continuar permitindo que o valor do cabeçalho Cache-Control
influencie a atualização do
/service-worker.js
, será necessário definir explicitamente updateViaCache: 'all'
ao
registrar o service worker.
Como pode haver um grande número de usuários em versões mais antigas do navegador, ainda é uma boa ideia
continuar definindo o cabeçalho HTTP Cache-Control: max-age=0
em scripts de worker de serviço, mesmo que
navegadores mais recentes possam ignorá-los.
Os desenvolvedores podem aproveitar essa oportunidade para decidir se querem explicitamente desativar o armazenamento em cache HTTP dos scripts importados agora e adicionar updateViaCache: 'none'
ao registro do service worker, se apropriado.
Como exibir scripts importados
A partir do Chrome 78, os desenvolvedores podem notar mais solicitações HTTP recebidas para
recursos carregados por importScripts()
, já que agora elas serão verificadas para
atualizações.
Se você quiser evitar esse tráfego HTTP adicional, defina cabeçalhos Cache-Control
de longa duração ao veicular scripts que incluem semver ou hashes nos
URLs e confie no comportamento padrão de updateViaCache
de 'imports'
.
Como alternativa, se você quiser que seus scripts importados sejam verificados para atualizações
frequentes, veicule-os com Cache-Control: max-age=0
ou use updateViaCache: 'none'
.
Leitura adicional
Os artigos O ciclo de vida do service worker e Práticas recomendadas de armazenamento em cache e armadilhas de idade máxima, ambos de Jake Archibald, são leituras recomendadas para todos os desenvolvedores que implantam algo na Web.