Comment créer un PWA avec Create-React-App et des travailleurs du service personnalisé

Remarque: il ne s'agit pas d'une introduction à create-react-app ou à ce qu'est un technicien de service. Ce poste suppose une connaissance préalable des deux.

J'ai donc récemment eu l'occasion de travailler sur un projet React qui impliquait la publication de l'application Web résultante en tant qu'application Web progressive (PWA).

J'ai réalisé à quel point il était difficile d'obtenir un PWA avec des itinéraires personnalisés configurés à l'intérieur d'une génération Create React App (CRA). Espérons que cela aide quelqu'un coincé dans une position similaire.

PWA dans Create-React-App

Comment pouvons-nous obtenir un PWA dans notre shell de l'ARC?

Maintenant, le shell CRA regroupe un agent de service par défaut. Vous devriez avoir remarqué que dans un shell CRA simple, à l'intérieur du fichier index.js, il existe un appel à registerServiceWorker:

Vous pouvez créer une nouvelle application de l'ARC et consulter le fichier registerServiceWorker.

Cela semble assez complexe, mais il s’agit en réalité de vérifier si les variables d’environnement sont définies pour une version de production et si un serviceWorker est pris en charge dans le navigateur actuel.

Si vous exécutez une construction avec la commande yarn build, vous pouvez ouvrir le dossier de construction et vérifier à l'intérieur qu'un fichier service-worker.js a été généré. Il s'agit du fichier de travailleur de service par défaut que l'ARC génère pour vous.

Le formatage du fichier est JavaScript ES5 intégré, ce qui le rend un peu difficile à lire. Mais vous pouvez le vider dans n’importe quel prétendant et vous devriez voir un fichier plus lisible.

En regardant dans le fichier ci-dessus, vous constaterez qu'il crée simplement un cache statique avec le nom de cache suivant: sw-precache-v3-sw-precache-webpack-plugin - + (selg.registration? Self.registration.scope). Il met ensuite en cache tous vos fichiers statiques tels que index.html et vos fichiers js et css à l'intérieur de ce cache.

Vous devriez également voir un écouteur d'événement fetch qui attrape un événement fetch et vérifie si l'application demande l'un des actifs statiques précédemment mis en cache.

Vient maintenant la question à un million de dollars: que se passe-t-il si vous souhaitez configurer un cache dynamique pour un itinéraire spécifique? Essentiellement, un cache qui se mettra à jour avec les données envoyées par le serveur lorsque l'utilisateur visite un itinéraire spécifié. Notez que cela signifie que les données ne seront pas disponibles au moment de la construction et ne peuvent donc pas être mises en cache par l'agent de service par défaut généré.

Limites des PWA par défaut dans l'ARC

Malheureusement, il n’est pas très facile de réaliser ce qui précède avec l’ARC. À moins que vous ne souhaitiez vous éjecter, bien sûr.

Examinez ces problèmes liés à GitHub pour comprendre pourquoi l'équipe de l'ARC ne prend pas en charge la personnalisation du service worker par défaut.

Donc, étant donné que nous ne pouvons pas sembler personnaliser le travailleur par défaut, comment pouvons-nous nous en sortir?

Comprendre comment l’ARC génère un agent de service

La première étape pour trouver une solution de contournement pour le système de construction consiste à comprendre réellement le fonctionnement du système de construction.

Commençons donc par la bibliothèque utilisée par le système de génération pour générer un fichier Service worker.

sw-precache est une bibliothèque qui vous permet de générer un fichier de travailleur de service basé sur un modèle. Le fichier de modèle est écrit à l’aide du moteur de gabarit de soulignement.

Voici le lien vers le fichier de modèle dans le code source sw-precache.

Encore une fois, le fichier de gabarit semble complexe, mais il est assez simple une fois que vous parvenez à vous familiariser avec le langage de gabarit.

Ainsi, que se passe-t-il lorsque vous exécutez un processus de construction dans un shell ARC, en rapport avec la génération d'un agent de service,

  1. La bibliothèque sw-precache est exécutée en interne
  2. Un objet options est fourni à sw-precache pour permettre la génération du fichier de travailleur de service à partir du modèle.
  3. Le fichier de travailleur de service est généré dans le dossier de construction avec le nom service-worker.js.

Remplacement du travailleur par défaut

Maintenant, comment pouvons-nous remplacer le processus ci-dessus pour permettre à notre propre fichier de travailleur de service personnalisé d'être généré?

La réponse est basée sur la réponse de stackoverflow de Jeff Posnick (responsable de sw-precache).

Premièrement, nous devons exécuter la CLIw-precache après le processus de construction normal.

Installez la bibliothèque sw-precache en exécutant la commande suivante: npm install --save-dev sw-precache

Maintenant, la bibliothèque sw-precache s'exécute sur un fichier de configuration, fourni via une option de la CLI. Voici la commande: sw-precache --config = sw-precache-config.js, où sw-precache-config.js est le nom du fichier de configuration.

Voici un exemple de fichier de configuration.

module.exports = {
  staticFileGlobs: [
    'build / static / css / **. css',
    'build / static / js / **. js'
  ],
  swFilePath: './build/service-worker.js',
  templateFilePath: './service-worker.tmpl',
  stripPrefix: 'construire /',
  handleFetch: false,
  runtimeCaching: [{
    urlPattern: /this\\.is\\.a\\.regex/,
    gestionnaire: 'networkFirst'
  }]
}

Remarque: Il est important de spécifier swFilePath sous la forme ./build/service-worker.js afin que le prestataire de services généré à la suite de votre processus de génération personnalisé écrase celui créé par CRA (ils partagent le même nom, dans ce cas). Sinon, vous aurez deux fichiers de travailleur de service dans votre répertoire de construction!

Il existe une documentation complète sur les propriétés de l'objet et sur les valeurs valides pouvant être attribuées sur la page GitHub pour sw-precache.

L'option runtimeCaching présente un intérêt particulier, car il s'agit d'une solution très extensible vous permettant de définir des règles personnalisées pour que votre agent de service réponde au contenu dynamique.

Le templateFilePath est une option pour quand vous voulez que la CLI récupère votre fichier de modèle de travailleur de service personnalisé. Mais vous utiliserez presque toujours le fichier de modèle fourni par la bibliothèque elle-même.

Enfin, nous devons fournir le script indiquant au système de génération de l'ARC que nous souhaitons que notre opérateur de service personnalisé soit généré. Allez-y et installez la bibliothèque sw-precache.

Ensuite, mettez à jour le script de génération package.json avec les éléments suivants:

construire: react-scripts construire && sw-precache --config = sw-precache-config.js

Une fois que vous avez exécuté le processus de construction avec npm run build, vous pouvez ouvrir le dossier de construction et voir votre service worker généré.

Exécutez le processus de génération avec et sans l’opérateur de service personnalisé et notez les différences entre les deux.

Conclusion

Bien que cela puisse sembler une approche très prolixe d'une tâche aussi simple que de personnaliser un prestataire de services, cette approche présente l'avantage de vous maintenir fermement dans le shell create-react-app.

Il existe d'autres approches pour générer un opérateur de service personnalisé (en utilisant une combinaison de react-app-rewire et de workbox). Je vais essayer de mettre cette approche en place également.