Uma alternativa moderna para importScripts().
Contexto
Módulos ES já são um dos favoritos dos desenvolvedores há algum tempo. Além de um vários outros benefícios, oferecem a promessa de um formato de módulo universal em que o código compartilhado pode ser lançados uma vez e executados em navegadores e em ambientes de execução alternativos, como Node.js: todos os navegadores modernos oferecem suporte a módulos ES, nem todos oferecem suporte em todos os lugares código pode ser executado. Especificamente, o suporte à importação de módulos ES dentro de uma do navegador service worker está começando a se tornar mais amplamente disponível.
Este artigo detalha o estado atual do suporte ao módulo ES em service workers em navegadores comuns, junto com algumas pegadinhas que devem ser evitadas e as práticas recomendadas para envio de código de service worker compatível com versões anteriores.
Casos de uso
O caso de uso ideal para módulos ES dentro de service workers é carregar uma biblioteca moderna ou código de configuração compartilhado com outros ambientes de execução que oferecem suporte a módulos ES.
A tentativa de compartilhar código dessa forma antes dos módulos ES implicava o uso de versões "universal" formatos de módulo diferentes, como UMD, que incluem código boilerplate desnecessário e código que fez alterações variáveis.
Os scripts importados por módulos ES podem acionar o service worker
atualizar
se o conteúdo mudar, correspondendo
comportamento
de
importScripts()
.
Limitações atuais
Somente importações estáticas
Os módulos ES podem ser importados de duas maneiras:
estaticamente,
usando a sintaxe import ... from '...'
ou
de forma dinâmica,
usando o método import()
. Dentro de um service worker, somente o
tem suporte no momento.
Essa limitação é análoga a uma
restrição semelhante
colocado no uso de importScripts()
. As chamadas dinâmicas para importScripts()
não
trabalham dentro de um service worker e todas as chamadas importScripts()
, que são
que é inerentemente síncrona, deve ser concluída antes que o service worker
install
. Essa restrição garante que o navegador saiba e saiba
armazenar em cache implicitamente, todo o código JavaScript necessário para a operação
durante a instalação.
Essa restrição pode ser removida, e o ES dinâmico importações de módulo podem ser permitidos. Por enquanto, use apenas a sintaxe estática dentro do um service worker.
E os outros workers?
Suporte para
Módulos ES em "dedicado" workers: aqueles que
construída com new Worker('...', {type: 'module'})
, é mais generalizada e
tem suporte no Chrome e no Edge desde
versão 80, bem como
versões recentes do Safari.
As importações de módulo ES estático e dinâmico são compatíveis com workers dedicados.
O Chrome e o Edge têm módulos ES compatíveis com o workers compartilhados desde a versão 83, mas ainda outros navegadores já oferecem suporte.
Não há suporte para a importação de mapas
Importar mapas permitem ambientes de execução para reescrever os especificadores de módulo, por exemplo, adicionando o URL de uma CDN preferencial de onde os módulos ES podem ser carregados.
Enquanto o Chrome e o Edge versão 89 e mais recente oferecem suporte à importação de mapas, eles atualmente não pode ser usado com o serviço trabalhadores
Suporte ao navegador
Os módulos ES em service workers são compatíveis com o Chrome e o Edge, começando com versão 91.
O Safari adicionou suporte ao Versão 122 da Prévia da tecnologia, Essa funcionalidade será lançada na versão estável do Safari no futuro.
Exemplo de código
Este é um exemplo básico de como usar um módulo ES compartilhado no window
de um app da Web.
contexto, além de registrar um service worker que usa o mesmo módulo ES:
// Inside config.js:
export const cacheName = 'my-cache';
// Inside your web app:
<script type="module">
import {cacheName} from './config.js';
// Do something with cacheName.
await navigator.serviceWorker.register('es-module-sw.js', {
type: 'module',
});
</script>
// Inside es-module-sw.js:
import {cacheName} from './config.js';
self.addEventListener('install', (event) => {
event.waitUntil((async () => {
const cache = await caches.open(cacheName);
// ...
})());
});
Compatibilidade com versões anteriores
O exemplo acima funcionaria bem se todos os navegadores fossem compatíveis com módulos ES em service workers, mas, no momento, esse não é o caso.
Para acomodar navegadores que não têm suporte integrado, você pode executar seu
script do service worker por meio de uma
bundler compatível com módulo ES para criar um
service worker que inclui todo o código do módulo inline e funcionará
navegadores mais antigos. Como alternativa, se os módulos que você estiver tentando importar forem
já está disponível no pacote
IIFE ou
UMD, podem ser importados usando
importScripts()
.
Assim que você tiver duas versões do service worker disponíveis, uma que use ES módulos e outro que não tem, será preciso detectar o que com suporte do navegador e registre o script do service worker correspondente. Os melhores as práticas recomendadas para detectar suporte estão em constante fluxo, mas é possível acompanhar discussão neste Problema no GitHub para recomendações.
_Foto por Vlado Paunovic em Unsplash_