Ajustes em cache.addAll() e importScripts() serão lançados no Chrome 71

Os desenvolvedores que usam service workers e a API Cache Storage precisam ficar de olho em duas pequenas mudanças lançadas no Chrome 71. Ambas as mudanças alinham a implementação do Chrome com as especificações e outros navegadores.

Como desativar o importScripts() assíncrono

importScripts() informa ao script principal do service worker para pausar a execução atual, fazer o download de outro código de um determinado URL e executá-lo até a conclusão no escopo global atual. Depois disso, o script principal do worker de serviço retoma a execução. importScripts() é útil quando você quer dividir seu script principal do service worker em partes menores por motivos organizacionais ou extrair código de terceiros para adicionar funcionalidade ao seu service worker.

Os navegadores tentam mitigar os possíveis problemas de desempenho de "fazer o download e executar algum código síncrono" armazenando em cache automaticamente tudo o que é puxado por importScripts(). Isso significa que, após o download inicial, há pouca sobrecarga envolvida na execução do código importado.

Para que isso funcione, o navegador precisa saber que não haverá nenhum código "surpresa" importado para o service worker após a instalação inicial. De acordo com a especificação do service worker, chamar importScripts() só deve funcionar durante a execução síncrona do script do service worker de nível superior ou, se necessário, de forma assíncrona dentro do gerenciador install.

Antes do Chrome 71, chamar importScripts() de forma assíncrona fora do gerenciador install funcionava. A partir do Chrome 71, essas chamadas geram uma exceção de execução, a menos que o mesmo URL tenha sido importado anteriormente em um gerenciador install, correspondendo ao comportamento em outros navegadores.

Em vez de um código como este:

// This only works in Chrome 70 and below.
self.addEventListener('fetch', event => {
  importScripts('my-fetch-logic.js');
  event.respondWith(self.customFetchLogic(event));
});

O código do worker de serviço vai ficar assim:

// Move the importScripts() to the top-level scope.
// (Alternatively, import the same URL in the install handler.)
importScripts('my-fetch-logic.js');
self.addEventListener('fetch', event => {
  event.respondWith(self.customFetchLogic(event));
});

URLs repetidos descontinuados transmitidos para cache.addAll()

Se você estiver usando a API Cache Storage com um worker de serviço, haverá outra pequena mudança no Chrome 71 para se alinhar à especificação relevante. Quando o mesmo URL é transmitido várias vezes para uma única chamada para cache.addAll(), a especificação diz que a promessa retornada pela chamada precisa ser rejeitada.

Antes do Chrome 71, isso não era detectado, e os URLs duplicados eram ignorados.

Uma captura de tela da mensagem de aviso no console do Chrome
A partir do Chrome 71, você verá uma mensagem de aviso registrada no console.

Esse registro é um prelúdio para o Chrome 72, em que, em vez de apenas um aviso registrado, URLs duplicados levarão à rejeição de cache.addAll(). Se você estiver chamando cache.addAll() como parte de uma cadeia de promessas transmitida para InstallEvent.waitUntil(), como é prática comum, essa rejeição poderá fazer com que a instalação do service worker falhe.

Confira como você pode ter problemas:

const urlsToCache = [
  '/index.html',
  '/main.css',
  '/app.js',
  '/index.html', // Oops! This is listed twice and should be removed.
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('my-cache').then(cache => cache.addAll(urlsToCache))
  );
});

Essa restrição se aplica apenas aos URLs reais transmitidos para cache.addAll(), e o armazenamento em cache do que acaba sendo duas respostas equivalentes com URLs diferentes, como '/' e '/index.html', não aciona uma rejeição.

Testar a implementação do worker do serviço amplamente

Os service workers são amplamente implementados em todos os principais navegadores "evergreen". Se você testa regularmente seu Progressive Web App em vários navegadores ou se tem um número significativo de usuários que não usam o Chrome, é provável que você já tenha detectado a inconsistência e atualizado seu código. Caso você não tenha percebido esse comportamento em outros navegadores, quisemos informar a mudança antes de mudar o comportamento do Chrome.