tl;dr
A partir do Chrome 68, as solicitações HTTP que verificam se há atualizações para o script do service worker não serão mais atendidas pelo cache HTTP por padrão. Isso resolve um problema comum com o desenvolvedor,
em que a configuração de um cabeçalho Cache-Control
inadvertida no script do service worker pode levar
a atualizações atrasadas.
Se você já desativou o armazenamento em cache HTTP para seu script /service-worker.js
veiculando-o
com Cache-Control: max-age=0
, não verá nenhuma alteração devido ao novo comportamento
padrão.
Além disso, a partir do Chrome 78, a comparação byte a byte será
aplicada aos scripts carregados em um service worker via
importScripts()
.
Qualquer alteração feita em um script importado acionará o
fluxo de atualização do service worker,
assim como uma alteração no service worker de nível superior faria.
Contexto
Sempre que você navegar para uma nova página no escopo de um service worker, chame explicitamente registration.update()
do JavaScript ou quando um service worker for "ativado" por um evento push
ou sync
, o navegador
vai solicitar, em paralelo, o recurso JavaScript que foi originalmente transmitido à
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 o código adicional que é executado dentro do service worker:
// Inside our /service-worker.js file:
importScripts('path/to/import.js');
// Other top-level code goes here.
O que está mudando?
Antes do Chrome 68, a solicitação de atualização de /service-worker.js
era feita pelo cache HTTP,
como a maioria das buscas. Isso significa que, se o script foi enviado originalmente com Cache-Control:
max-age=600
, as atualizações nos próximos 600 segundos (10 minutos) não iriam para a rede. Portanto, o
usuário pode não receber a versão mais atualizada do service worker. No entanto, se max-age
for
maior que 86.400 (24 horas), ele será tratado como se fosse 86.400, para evitar que os usuários fiquem presos
a uma versão específica para sempre.
A partir da versão 68, o cache HTTP será ignorado quando você solicitar atualizações para o script do service worker. Portanto, os aplicativos da Web atuais poderão ter um aumento na frequência das solicitações para o script do service worker. As solicitações de importScripts
ainda serão feitas pelo cache HTTP. No entanto, esse é
apenas o padrão. Uma nova opção de registro, updateViaCache
, que oferece controle sobre
esse comportamento, está disponível.
updateViaCache
Agora, os desenvolvedores podem transmitir uma nova opção ao chamar navigator.serviceWorker.register()
: o parâmetro updateViaCache
.
Ele usa um destes três valores: 'imports'
, 'all'
ou 'none'
.
Os valores determinam se e como o cache HTTP padrão do navegador entra em jogo 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 durante a verificação de atualizações para o script/service-worker.js
, mas será consultado ao buscar qualquer script importado (no nosso exemplo,path/to/import.js
). 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 quaisquer scripts importados dentro do service worker, 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 qualquer script importado, como opath/to/import.js
hipotético.
Por exemplo, o código a seguir registrará um service worker e garantirá que o cache HTTP
nunca seja consultado ao verificar atualizações para o script /service-worker.js
ou para 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 para scripts importados
Antes do Chrome 78, qualquer script de service worker carregado por
importScripts()
só era recuperado uma vez (verificando primeiro no cache HTTP ou pela
rede, dependendo da configuração de updateViaCache
). Após essa recuperação
inicial, ela é armazenada internamente pelo navegador e nunca é buscada novamente.
A única maneira de forçar um service worker já instalado a captar alterações em
um script importado era alterar 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 alteração do URL importado é que a mudança de conteúdo do script
do service worker de nível superior, que, por sua vez, aciona o fluxo de trabalho de serviço.
A partir do Chrome 78, sempre que uma verificação de atualização for realizada para um arquivo
de service worker de nível superior, serão feitas verificações ao mesmo tempo para determinar se
o conteúdo de algum script importado foi alterado. Dependendo dos cabeçalhos Cache-Control
usados, essas verificações de script importados poderão ser realizadas pelo cache HTTP se updateViaCache
estiver definido como 'all'
ou 'imports'
(que é o valor padrão), ou as verificações poderão ir diretamente para a rede se updateViaCache
estiver definido como 'none'
.
Se uma verificação de atualização para um script importado resultar em uma diferença byte por byte em comparação com o que foi armazenado anteriormente pelo service worker, isso acionará o fluxo completo de atualização do service worker, mesmo que o arquivo do service worker de nível superior permaneça o mesmo.
O comportamento do Chrome 78 corresponde ao que o Firefox implementou há vários anos, no Firefox 56. O Safari também já implementa esse comportamento.
O que os desenvolvedores precisam fazer?
Se você desativou o armazenamento em cache HTTP para seu script /service-worker.js
exibindo-o
com Cache-Control: max-age=0
(ou um valor semelhante), não verá nenhuma alteração devido ao
novo comportamento padrão.
Se você exibir o script /service-worker.js
com o armazenamento em cache HTTP ativado, seja intencionalmente
ou porque é apenas o padrão do seu ambiente de hospedagem,
poderá começar a ver um aumento de solicitações HTTP adicionais para /service-worker.js
feitas no
seu servidor. Essas são solicitações 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
, comece a definir explicitamente updateViaCache: 'all'
ao
registrar seu service worker.
Como pode haver uma cauda longa de usuários em versões de navegadores mais antigas, ainda é uma boa ideia
continuar definindo o cabeçalho HTTP Cache-Control: max-age=0
nos scripts do service worker, mesmo que
os navegadores mais recentes possam ignorá-los.
Os desenvolvedores podem usar essa oportunidade para decidir se querem desativar explicitamente os scripts
importados do armazenamento em cache HTTP agora e adicionar updateViaCache: 'none'
ao registro do
service worker.
Exibição de scripts importados
A partir do Chrome 78, os desenvolvedores podem ver mais solicitações HTTP recebidas para
recursos carregados via importScripts()
, já que serão verificadas
se há atualizações.
Se você quiser evitar esse tráfego HTTP extra, defina cabeçalhos
Cache-Control
de longa duração ao exibir scripts que incluem semver ou hashes nos
URLs e confie no comportamento updateViaCache
padrão de 'imports'
.
Como alternativa, se você quiser verificar se há atualizações frequentes nos scripts importados, veicule-os com Cache-Control: max-age=0
ou use updateViaCache: 'none'
.
Leia mais
As leituras The Service Worker Lifecycle e Práticas recomendadas em cache e armadilhas de max-age, de Jake Archibald, são recomendadas para todos os desenvolvedores que implantam qualquer coisa na Web.