Modules ES dans les service workers

Alternative moderne à importScripts().

Contexte

Modules ES est l'une des applications préférées des développeurs depuis un moment. En plus d'un de nombreux autres avantages, ils offrent la promesse d'un format de module universel dans lequel le code partagé peut être publiées une seule fois et s'exécutent dans des navigateurs et d'autres environnements d'exécution, comme Node.js Alors que tous les navigateurs récents proposent une assistance pour les modules ES, mais pas partout où peut être exécuté. Plus précisément, la prise en charge de l'importation de modules ES à l'intérieur d'un navigateur service worker commence tout juste à être plus largement disponible.

Cet article décrit l'état actuel de la compatibilité du module ES avec les service workers. des navigateurs courants, ainsi que quelques pièges à éviter et les bonnes pratiques l'envoi de code de service worker compatible avec les versions antérieures.

Cas d'utilisation

Le cas d'utilisation idéal des modules ES dans les service workers consiste à charger une bibliothèque ou un code de configuration moderne qui est partagé avec d'autres environnements d'exécution prend en charge les modules ES.

Tentative de partage de code de cette manière avant les modules ES impliquant d'utiliser d'anciennes "universel" formats de module comme UMD, qui incluent code récurrent inutile, et écriture de code apportant des modifications à des ressources exposées de manière globale variables.

Les scripts importés via des modules ES peuvent déclencher le service worker mise à jour en cas de modification du contenu, comportement de importScripts()

Limites actuelles

Importations statiques uniquement

Les modules ES peuvent être importés de deux manières : de manière statique, à l'aide de la syntaxe import ... from '...' ; de façon dynamique, à l'aide de la méthode import(). Dans un service worker, seule la couche statique est actuellement acceptée.

Cette limitation s'apparente restriction similaire qui est basé sur l'utilisation de importScripts(). Les appels dynamiques à importScripts() ne fonctionnent dans un service worker, ainsi que tous les appels importScripts(), qui sont par nature synchrones, doivent s'effectuer avant que le service worker n'ait terminé install. Cette restriction garantit que le navigateur connaît et mettre en cache implicitement tout le code JavaScript nécessaire au fonctionnement lors de l'installation.

Il est possible que cette restriction soit levée, et l'ES dynamique importations de modules peuvent être autorisées. Pour l'instant, veillez à n'utiliser que la syntaxe statique à l'intérieur de un service worker.

Qu'en est-il des autres nœuds de calcul ?

Assistance pour Modules ES dans des les nœuds de calcul, c'est-à-dire construite avec new Worker('...', {type: 'module'}), est plus répandue, et est pris en charge dans Chrome et Edge depuis version 80, ainsi que versions récentes de Safari. Les importations de modules ES statiques et dynamiques sont compatibles avec les nœuds de calcul dédiés.

Chrome et Edge disposent de modules ES compatibles dans nœuds de calcul partagés depuis la version 83, mais pas un autre navigateur est actuellement compatible.

Impossible d'importer des cartes

Importer des cartes permet environnements d'exécution pour réécrire les spécificateurs de module afin, par exemple, d'ajouter le préfixe URL du CDN préféré à partir duquel les modules ES peuvent être chargés.

Alors que Chrome et Edge version 89 ou ultérieure prennent en charge l'importation de cartes, ne peut pas être utilisé avec le service les nœuds de calcul.

Prise en charge des navigateurs

Les modules ES des service workers sont compatibles avec Chrome et Edge, à partir de version 91.

Safari est désormais pris en charge dans Version Preview technologique 122, et les développeurs doivent s'attendre à ce que cette fonctionnalité soit disponible dans la version stable de Safari.

Exemple de code

Voici un exemple de base d'utilisation d'un module ES partagé dans le window d'une application Web tout en enregistrant un service worker qui utilise le même module 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);
    // ...
  })());
});

Rétrocompatibilité

L'exemple ci-dessus fonctionnerait bien si tous les navigateurs acceptaient les modules ES dans mais ce n'est pas le cas à ce stade.

Pour vous adapter aux navigateurs qui ne sont pas compatibles, vous pouvez exécuter votre de service worker via un Bundler compatible avec le module ES pour créer un qui inclut tout le code du module de façon intégrée et fonctionne dans des navigateurs plus anciens. Si les modules que vous tentez d'importer sont déjà disponible dans une offre groupée IIFE ou UMD, vous pouvez les importer importScripts()

Lorsque deux versions de votre service worker sont disponibles, l'une utilisant ES modules et celui de l'autre, vous devez détecter navigateur prend en charge et enregistre le script service worker correspondant. Le meilleur les pratiques de détection de la prise en charge sont en cours de développement, mais vous pouvez suivre discussion dans ce Problème GitHub pour recommandations.

_Photo par Vlado Paunovic sur Unsplash_