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 estar atentos a duas pequenas mudanças que serão lançadas no Chrome 71. Ambas as mudanças deixam a implementação do Chrome mais alinhada às especificações e aos outros navegadores.

Proibir importScripts() assíncrono

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

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

Para que isso funcione, no entanto, 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() deve funcionar apenas 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 funcionaria. A partir do Chrome 71, essas chamadas geram uma exceção de tempo 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 assim:

// 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 service worker 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));
});

Suspensão do uso de URLs repetidos transmitidos para cache.addAll()

Se você estiver usando a API Cache Storage com um service worker, haverá outra pequena mudança no Chrome 71 para se alinhar à especificação relevante. Quando o mesmo URL é transmitido várias vezes a 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.

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

Veja 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 que estão sendo transmitidos para cache.addAll(). O armazenamento em cache do que acaba sendo duas respostas equivalentes com URLs diferentes, como '/' e '/index.html', não vai acionar uma rejeição.

Testar amplamente a implementação do service worker

Os service workers estão amplamente implementados em todos os principais navegadores"duradouros" neste momento. Se você testa seu Progressive Web App regularmente em vários navegadores ou tem um número significativo de usuários que não usam o Chrome, é provável que já tenha detectado a inconsistência e atualizado seu código. Mas, como você não percebeu esse comportamento em outros navegadores, queremos destacar a mudança antes de mudar o comportamento do Chrome.