web-dev-qa-db-fra.com

Comment gérer le routage dans Angular 5+ Service Workers?

Dans les versions précédentes de l'implémentation du travailleur de service Angular, une des options de configuration était "routing". Cela peut être vu dans ce sans réponse SO question , a été référencé dans ce problème de CLI angulaire , et la meilleure documentation restante semble être la article de blog de Stephen Fluin (sur l'équipe Angular), ainsi que I/O talk d'Alex Rickabaugh (de Google) .

Avec Angular 5, le ServiceWorkerModule a été bien construit, et la plupart de la configuration peut maintenant être gérée en utilisant le ngsw-config.json fichier. Cependant, il n'y a plus aucune mention de la façon de gérer la redirection pour les itinéraires, nulle part dans le guide angular.io , ou dans le documentation . Je me retrouve donc avec le problème suivant: lorsque j'ai visité mon application et que je suis hors ligne, je peux toujours accéder à l'application en la visitant directement: https://jackkoppa.github.io/cityaq-sw-issue . Cependant, lors du chargement, l'application redirige vers la route search, et la plupart des utilisateurs essaient de charger à partir d'une URL comme https://jackkoppa.github.io/cityaq-sw-issue/search ? cities = Shanghai (pour plus de simplicité, je ne parle que de Chrome desktop & mobile, pour l'instant, et dans Incognito lorsque cela est possible).

Lorsque vous essayez de visiter cette URL en mode hors connexion, vous obtenez immédiatement 504 - Délai d'expiration de la passerelle. Cela se produit car le technicien de service n'a mis en cache que l'index et ne sait pas que les autres routes doivent rediriger vers l'index pour qu'il puisse se charger. Je suis convaincu que les itérations précédentes de la mise en œuvre de l'employé de service Angular) auraient pu gérer ce scénario, en configurant des redirections vers l'index pour les routes données. Y a-t-il un moyen de gérer cette redirection dans le courant, Angular 5+ ngsw-config.json, ou dans le ngsw.json fichier? À part cela, comment une solution de contournement devrait-elle être gérée dans un fichier JS de service worker séparé?

29
Jack Koppa

TL; DR: J'ai identifié au moins deux problèmes provoquant des bris dans mon cas; vous pouvez utiliser ce script de construction pour l'instant pour essayer ma solution, et voir l'application fonctionner hors ligne ici . D'autres tests et demandes d'extraction sont nécessaires.


Bien que je n'aie pas pu trouver de réponse documentée, voici ce que j'ai pu trouver jusqu'à présent, en parcourant le ngsw-worker.js fichier, ainsi que la lecture du @angular/service-worker historique de validation.

La nouvelle approche ServiceWorkerModule du "routage" consiste à prendre toute demande de "navigation" (c'est-à-dire une route non indexée sur le même domaine) et à réexécuter la méthode handleFetch, mais en pointant maintenant au index.html requête ( source ). Cela devrait fonctionner correctement, étant donné qu'un SPA devrait être en mesure de rediriger vers l'URL une fois qu'il a récupéré ses fichiers mis en cache pour l'index.

Ainsi, les problèmes qui provoquent l'échec de mon site ci-dessus lorsqu'il est hors ligne ne doivent pas être directement liés au routage, et j'en ai trouvé 2 jusqu'à présent. Les corriger avec une solution de contournement m'a permis de faire fonctionner mon application comme prévu. Avec les étapes de repro dans la question d'origine, cityaq fonctionne maintenant, alors que j'ai reproduit le site défaillant d'origine sur cityaq-sw-issue .

Les problèmes:

  1. Versions hébergées d'une application Angular, où --base-href L'indicateur est défini à partir de l'interface CLI, liste les URL absolues pour leurs ressources de service worker. Lorsque vous comparez des demandes à ces ressources, ngsw-worker.js attend des URL relatives

    • source
    • Je suis assez confiant que ce problème doit être résolu, et je vais travailler sur une demande d'extraction pour le résoudre. Cela se produit parce que baseHref est inclus dans les URL des ressources lorsque ngsw.json est généré ( source )
  2. Sur les 3 "états" disponibles, le ngsw-worker.js peut être, d'après mon expérience, EXISTING_CLIENTS_ONLY semble ne pas être réglé correctement.

    • source 1 , source 2
    • Je suis moins confiant quant à ce changement, car je n'ai pas été en mesure de toujours voir quoi provoquer cet état. Cependant, si et lorsque le travailleur de service entre dans cet état, ngsw-worker.js n'essaiera plus de récupérer les ressources mises en cache ( source ), et dans mes tests dans ce qui semble être des circonstances "correctes", l'application entre toujours dans cet état même lorsque la seule modification consiste à supprimer un Internet connexion

Pendant que je prépare un PR pour le problème n ° 1 et que j'attends de l'aide pour comprendre le problème n ° 2, j'utilise un script de génération de contournement pour modifier ngsw-worker.js après sa génération. Avertissement: il est laid et modifie définitivement le comportement "sûr" prévu de la configuration EXISTING_CLIENTS_ONLY. Cependant, pour mon application, elle permet des performances hors ligne correctes lors de l'exécution locale (http-server), et déploiement sur une URL en direct (pages GitHub, dans mon cas).

Pour utiliser la solution de contournement: (Angular 5, testé avec Angular 5.2.1)

  1. npm install replace-in-file --save-dev
  2. Inclure ce script dans votre application, par ex. à build/fix-sw.js
  3. Dans votre package.json:
"scripts": {
   ...
   "sw-build": "ng build --prod && node build/fix-sw",
   "sw-build-live": ng build --prod --base-href https://your-url.com/ && node build/fix-sw"
   ...
}
  1. Pour exécuter localement
npm exécuter sw-build 
 cd dist 
 http-server -p 8080
  1. Et pour préparer une construction pour votre URL en direct, avant de l'envoyer à un serveur (par exemple avec angular-cli-ghpages )
npm exécuter sw-build-live
8
Jack Koppa