Les services workers

Ces derniers mois j’ai eu l’occasion de découvrir et tester certaines technos (en pro et en perso). Avant de passer à 2020, petit tour d’horizon des services workers.

Notions utiles

Hormis bien sûr LA notion de ce billet, à savoir « les services workers », une autre est importante : le offline. Littéralement « hors connexion« , l’idée est de proposer une meilleure expérience, que dis-je une expérience tout court, dans ce mode.

On parle de plus en plus de « Offline First web sites and applications ». A l’instar du mobile first qui consiste à s’intéresser en premier au mobile, le offline first se concentre sur le offline.

Cela a du sens à bien des égards, parmi ces raisons, la possibilité de pouvoir continuer à naviguer sur mon blog fétiche sans avoir de connexion aux Internets (ou Interlinks ^^). Pour autant, ce n’est pas l’ultime but mais c’est déjà pas mal.

Par extension à offline first, on retrouve le mobile en ligne de mire, avec lequel je faisais une analogie plus haut, et les PWA. Le web ne sait pas du tout gérer ce mode hors connexion !

Un autre point important est que la technique évolue rapidement et va nécessairement se généraliser dans les prochaines années (à moins d’être renversée par une technique concurrente ^^), même les navigateurs les plus en retard annoncent une compatibilité à venir.

Premiers pas avec les workers

Bon c’est quoi déjà ce truc ?!! Pour le dire simplement, c’est une API qui vit quelque part dans le navigateur et qui permet aux développeurs de scripter des codes qui vont tourner en tâche de fond.

Autrement dit, du code qui vit en dehors de la page web, sans interaction avec un quelconque utilisateur.

Une clé ici pour comprendre est que l’API nous permet de gérer l’expérience offline. Une autre clé est qu’elle nous permet d’intercepter des requêtes faites sur le réseau…

L’ API est fondée sur les promesses et les événements. Pour celles et ceux qui ne cliqueront pas sur le lien, les promesses sont des objets qui donnent une représentation d’un succès ou d’un échec. On y des fait des appels asynchrones.

Démo rapido

Pour enregistrer un service worker, il faut entourer le code avec :

if ('serviceWorker' in navigator) {
} else {
    console.error('ce navigateur ne supporte pas les services workers. Ils ne se connaissent pas encore assez bien mais ils vont apprendre :)');
}

car, à l’heure où j’écris ce billet, tous les navigateurs ne le supportent pas, et parmi ceux qui le supportent, c’est souvent dans leurs dernières versions…

Encore une fois, ça va aller en s’améliorant, c’est une tendance de fond et en plus ça nous permet d’utiliser les derniers outils d’ES (ECMAScript) dont async et await.

Pour écrire notre enregistrement, on peut écrire :

window.addEventListener('load', () => {
  if (!('serviceWorker' in navigator)) {
      console.log('Service workers are not supported.');
      return;// stop l'exécution, erreur critique
  }

  navigator.serviceWorker.register('/sw.js').then(
    () => {
         console.log('Service worker registration succeeded:', registration);
            
    },
    err => {
      console.log('Service worker registration failed:', error)
    }
  )
})

Cycle et vie

Je le disais au-dessus, les services workers vivent en dehors de la page web. Pour pouvoir les utiliser il faut les enregistrer dans le navigateur.

Après enregistrement, le navigateur va lancer l’installation de manière asynchrone. A la moindre erreur, si votre script plante, le service worker entier ne sera ni installé ni activé.

Soulevons un peu le capot

L’ API possède une liste d’événements parmi lesquels :

  • fetch, déclenché chaque fois qu’une ressource contrôlée par un service worker est retournée,
  • install, déclenché à l’installation du service
  • activate, déclenché une fois le service enregistré dans le navigateur et après installation
  • push, déclenché quand un événement PUSH est reçu

Source

Autant de hooks possibles donc mais ce qui est intéressant en premier lieu ce sont les possibilités de cache avec le navigateur.

L’ exemple typique c’est la possibilité de mette en cache des assets à l’installation, autrement dit fichiers html, css, js, images, json, etc. Ainsi à la première installation, tout est mis en cache !

On parlait d’offline plus haut, ce fonctionnement le permet. En cas d’indisponibilité réseau ou de hors connexion, les ressources sont toujours servies.

Les stratégies de cache

Notre service worker va fonctionner comme un proxy dont on va se servir pour intercepter les requêtes sur le network.

On va pouvoir utiliser la cache API pour servir des assets sans avoir besoin de faire appel au réseau. La citation à faire est :

the fastest request is the one you never need to make

Cette étude est très parlante.

A noter que les stratégies de cache ne concernent pas seulement les états hors connexions. Il y en a une par exemple qu’on appelle « Stale while reva[ page.lang ].date » et qui consiste à servir du cache au client en lançant une requête en parallèle pour aller récupérer la nouvelle version.

Cette nouvelle version sera servie à la prochaine navigation. Le service worker s’occupe de faire l’aiguillage.

Quelques inconvénients

Pour le moment, les outils de debug dépendent des navigateurs…

Néanmoins, la console de votre navigateur devrait afficher un menu si votre navigateur supporte les services workers. Dans chrome, par exemple, c’est sous « Application ».

Un autre point d’attention : la stratégie de mise à jour, à savoir est-ce qu’il y a eu des changements. Le gain en performance est énorme mais il se peut qu’il y ait des cas où cela plante. Le fait de se mettre en position de proxy implique nécessairement certains écueils possibles.

Google a sorti et maintient une lib, entre autres, pour aider l’implémentation de ce genre de stratégies : workbox.js.

Gatsby et les services workers

Gatsby implément workbox.js déjà. Cela peut être un bon terrain de jeu encadré pour découvrir les services workers 🙂

Gatsby est fait pour créer non pas seulement des sites mais bel et bien des applications. Le mode offline est géré via deux plugins (manifest et le bien nommé offline).

Il est possible d’y enregistrer nos propres services workers en éditant le fichier gatsby-browser.js :

export const registerServiceWorker = () => true

Source

Conclusion

Voilà pour ce petit tour des service workers. Sujet à suivre ! Don’t trust the network 🙂

2019 s’achèvera sur ce blog sur cette thématique passionnante, il est temps de passer aux huitres !