Loupe

Blazor - Construire une PWA avec Blazor WebAssembly

J'ai eu la magnifique opportunité de présenter une session durant la BlazorDay online conference à propos de Construire une PWA avec Blazor WebAssembly (L'enregistrement est disponible sur Youtube)

Si vous préférez un format écrit, sous forme d'un court article de blog, plutôt que de regarder une vidéo de 30 minutes, vous êtes au bon endroit.

Workbox ou ne pas Workbox

tl;dr: Vous pouvez dire au revoir à Workbox :)

Comme vous avez pu le remarquer (ou non), cet article pourrait être considéré en partie comme une mise à jour d'un ancien article Blazor - partie 4 : Comment transformer une application Blazor en PWA avec Workbox.

À ce moment-là, le fonctionnement en mode PWA avec Blazor n'était pas supporté par défaut, et configurer le tout manuellement n'était pas ce qu'il y avait de plus trivial. De ce fait, utiliser un outil aussi reconnu et éprouvé que Workbox pour simplifier la mise en place d'une PWA semblait être une bonne solution.

Mais nous parlons d'un temps déjà très ancien ! (En fait nous parlons de seulement 8 mois plus tôt pour être plus exact haha) et à date, Blazor WebAssembly est maintenant officiellement disponible avec la version du .NET Core SDK 3.1.300+.

Au départ, je pensais que le support du mode PWA avec Blazor serait une implémentation trop simpliste, et aurait besoin d'être rapidement remplacé par un outillage plus robuste tel que Workbox... Mais j'ai très rapidement abandonné cette idée quand j'ai pu constater par moi-même le très bon travail fourni par l'équipe Blazor sur le sujet, qui fournit un système prêt à l'emploi, et facilement extensible !

Cependant, comme je reste convaincu que le sujet n'est pas toujours trivial (notamment la partie concernant le service-worker), voyons de plus près la magie opérée derrière la commande dotnet new blazorwasm -o MyNewProject --pwa (ou derrière la case à cocher Progressive Web Application qui se trouve dans Visual Studio)

Rendre son application installable

Pour rendre son application installable, rien d'extraordinaire de ce côté. Vous pouvez jeter un œil aux fichiers ajoutés et modifiés pour rendre votre application Blazor installable dans ce commit Github

N'oubliez également pas d'enregistrer un service worker, même vide, pour que votre application soit considérée comme une PWA aux yeux de lighthouse.

Pour plus d'information concernant tous les configurations possibles du manifest, n'hésitez pas à jeter un coup d’œil à la documentation officielle https://developer.mozilla.org/en-US/docs/Web/Manifest.

Ajout du support offline grâce au service-worker.js

Ok, les choses commencent à devenir intéressante à partir d'ici. Pour le support de l'offline, vous avez grosso modo besoin de 2 choses :

  1. La liste de tous les assets à rajouter au cache du navigateur
  2. Une description de comment vous souhaitez gérer l'utilisation et la mise à jour du cache de votre navigateur.

Pour ce premier point, Blazor fournit une propriété MSBuild appelée <ServiceWorkerAssetsManifest> qui va se charger de lister tous les fichiers publiés et produire un hash pour savoir si chaque fichier a changé ou non, pour enfin résumer toutes ces informations dans un fichier appelé service-worker-assets.js. (Plus de détail dans ce commit Github)

Pour la seconde partie, Blazor fournit un fichier additionnel appelé service-worker.published.js qui contient la réelle implémentation de notre stratégie de gestion du cache, par défaut une stratégie de Cache, falling back to network.

https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook#cache-falling-back-to-network *Schéma de la stratégie Cache, falling back to network provenant de developers.google.com/web/fundamentals

Cependant, et comme décrit dans la documentation officielle de Microsot, le support offline n'est "activé" que lorsque l'application est "publiée", ce qui signifie que le fichier service-worker.js n'est remplacé par le fichier service-worker.published.js que lorsque l'on utilise la commande dotnet publish (ou lorsque l'on publie depuis Visual Studio)

Et voilà, félicitations, votre application publiée fonctionne même en étant offline. Mais comme toujours, j'aime bien savoir ce qui se cache réellement derrière (pour pouvoir s'en servir / le faire évoluer correctement), voyons dans dans la prochaine partie plus en détail le contenu de ce service worker.

Les événements du cycle de vie du Service worker

Si l'on regarde le contenu du fichier service-worker.published.js, on peut y constater un workflow assez simple, fait en 4 parties :

  • Une référence self.assetsManifest vers le manifest des assets, contenant la liste des fichiers qui ont besoin d'être mis en cache, ainsi qu'une version calculée à partir de tous les hash des fichiers,
  • Une action pour l'événement installing d'installation du service worker,
  • Une action pour l’événement activating de son activation,
  • Et enfin une action pour l'événement fetching déclenché à chaque récupération d'une ressource.

En premier lieu, l'événement installing est appelé à chaque fois qu'une nouvelle version de la PWA est publiée, et permet la mise en cache de tous les assets décrits dans le manifest, dans un cache nommé suivant le numéro de version de l'application (calculée donc à partir de tous les hash des assets). Une fois l'installation terminée, la nouvelle version du service worker passe dans un état waiting, attendant que toutes les instances de la PWA soit fermées pour activer la nouvelle version.

Durant le processus d'activation (événement activating), le "nouveau" service worker devient la version "courante", et tous les caches correspondant à d'autres versions antérieures sont supprimés.

Enfin, à chaque fois qu'une ressource est demandée (telle qu'une image, une icone, un fichier html, javascript, etc.), l'événement fetch est déclenché et permet de vérifier si la ressource est présente dans le cache. Si elle l'est, la version en cache est retournée, aucune requête réseau (nécessitant une connexion internet par exemple) n'est déclenchée, et sinon, la requête http a lieu normalement.

Bon, malgré toutes ces explications, le sujet est peut-être encore un peu obscur, et je ne saurais que vous conseiller de "déboguer" en pas à pas par vous même ce service worker pour vous familiariser avec son fonctionnement.

Pour aller plus loin

La mise à jour d'un service worker est souvent de premier abord assez surprenante (le fait de devoir attendre que toutes les versions soient fermées), et l'on peut se demander s'il est possible de "notifier" l'utilisateur de la présence d'une nouvelle version, et lui donner la possibilité de "forcer une mise à jour immédiatement". Pour cela, on peut par exemple utiliser l'instruction self.skipWaiting(), ainsi qu'un canal de communication tel que l'API BroadcastChannel pour communiquer entre la PWA et le Service worker (Vous pourrez trouver un exemple sur mon Github)

01-blazor-progressive-web-app-update-now-button.png

Ceci étant dit, j'espère que cet article aura pu vous rafraîchir la mémoire si vous ne vous souvenez plus très bien de la session, ou vous aura permis de mieux appréhender ce sujet si vous préférez un format écrit que vidéo !

Comme toujours, n'hésitez pas à me contacter sur Twitter @vivienfabing ou dans les commentaires, et que le code soit avec vous !

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus