Moduli ES nei service worker

Un'alternativa moderna a importScripts().

Sfondo

Moduli ES sono le preferite degli sviluppatori da un po'. Oltre a un numero di altri vantaggi, offrono la promessa di un formato di moduli universale in cui il codice condiviso possa essere una volta rilasciate ed eseguite nei browser e in runtime alternativi, Node.js. Mentre tutti i browser moderni offrono supporto per i moduli ES, non tutti offrono supporto ovunque è possibile eseguire il codice. In particolare, il supporto per l'importazione dei moduli ES all'interno di un del browser Service worker è solo agli inizi.

Questo articolo descrive in dettaglio lo stato attuale del supporto dei moduli ES nei service worker nei browser più comuni, insieme ad alcuni trucchi da evitare e le best practice che spedisce codice del service worker compatibile con le versioni precedenti.

Casi d'uso

Il caso d'uso ideale per i moduli ES all'interno dei service worker è il caricamento di un una libreria moderna o un codice di configurazione condiviso con altri runtime e supportare i moduli ES.

Il tentativo di condividere il codice in questo modo prima dei moduli ES comportava l'utilizzo di "universale" formati di moduli come UMD che includono boilerplate non necessari e la scrittura di codice che apporta modifiche agli ambienti esposti a livello globale come la codifica one-hot delle variabili categoriche.

Gli script importati tramite moduli ES possono attivare il service worker aggiorna in caso di variazione dei contenuti, in base ai comportamento di importScripts().

Limitazioni attuali

Solo importazioni statiche

I moduli ES possono essere importati in due modi: in modo statico, utilizzando la sintassi import ... from '...' oppure in modo dinamico, utilizzando il metodo import(). All'interno di un service worker, solo lo stato è attualmente supportata.

Questa limitazione è analoga a un restrizione simile effettuata in base all'utilizzo di importScripts(). Le chiamate dinamiche a importScripts() non all'interno di un service worker e tutte le chiamate importScripts(), che sono di per sé sincrona, deve essere completata prima che il service worker completi la sua install fase. Questa restrizione garantisce che il browser sia a conoscenza e memorizzare nella cache, tutto il codice JavaScript necessario per lo sviluppo implementazione durante l'installazione.

Questa limitazione potrebbe essere revocata e lo stato dinamico di ES importazioni di moduli potrebbe essere consentito. Per il momento, assicurati di utilizzare solo la sintassi statica all'interno di un service worker.

E gli altri lavoratori?

Supporto per Moduli ES in "dedicato" worker, ovvero creata con new Worker('...', {type: 'module'}), è più diffusa è supportata in Chrome ed Edge versione 80, oltre a versioni recenti di Safari. Le importazioni di moduli ES statiche e dinamiche sono supportate nei worker dedicati.

Chrome ed Edge hanno moduli ES supportati in lavoratori condivisi dalla versione 83, ma non altri browser al momento offrono assistenza.

Nessun supporto per l'importazione delle mappe

Consenti Importa mappe ambienti runtime per riscrivere gli specificatori dei moduli, ad esempio anteporre URL di una rete CDN preferita da cui è possibile caricare i moduli ES.

Mentre Chrome ed Edge versione 89 e successive supportano l'importazione di mappe, al momento non può essere utilizzato con il servizio worker.

Supporto browser

I moduli ES nei service worker sono supportati in Chrome ed Edge a partire da versione 91.

Safari ha aggiunto il supporto Versione 122 di Anteprima tecnologica, e gli sviluppatori dovrebbero aspettarsi il rilascio di questa funzionalità di Safari in futuro.

Esempio di codice

Questo è un esempio base di utilizzo di un modulo ES condiviso in window di un'app web di contesto, registrando al contempo un service worker che utilizza lo stesso modulo 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);
    // ...
  })());
});

Compatibilità con le versioni precedenti

L'esempio precedente andrebbe bene se tutti i browser supportavano i moduli ES in ai service worker, ma al momento della stesura di questo articolo non è così.

Per supportare i browser che non dispongono di supporto integrato, puoi eseguire dello script del service worker tramite un Bundler compatibile con il modulo ES per creare un che includa tutto il codice del modulo in linea e che lavorerà browser meno recenti. In alternativa, se i moduli che stai tentando di importare sono già disponibile in bundle IIFE o UMD, puoi importarli utilizzando importScripts().

Quando sono disponibili due versioni del service worker, una che utilizza ES moduli e l'altra che non lo fa, dovrai rilevare quale che il browser supporti e registra lo script del service worker corrispondente. Il meglio le pratiche di rilevamento dell'assistenza sono in continua evoluzione, ma puoi seguire le in questa Problema GitHub per personalizzati.

_Foto di Vlado Paunovic su Unsplash_