
Comme vous le savez, ce blog est codé entièrement en React. Cela s'explique en partie par les circonstances dans lesquelles j'avais entrepris de le concevoir. Bien qu'elle présente comme avantage d'être extrêmement flexible, cette librairie a pour problème de ralentir la performance d'une application qui grandit.
Ce que je veux dire c'est que : oui, un DOM virtuel c'est cool et c'est même le concept qui m'a personnellement attiré quand j'ai décidé de l'apprendre. Le problème, c'est que tout est d'abord téléchargé sur l'appareil de l'utilisateur et s'y exécute. Or plus le projet grandit, plus on a des fichiers, plus on a des dépendances, ... plus on a des trucs à télécharger et donc, forcément, plus l'application devient lente.
Au début, quand j'ai rencontré ce problème, j'ai utilisé des solutions comme les rollups (intégrée à Vite), les lazy imports et la memoisation de certaines opérations. Le démon s'est calmé mais très vite ... il s'est réveillé !

Comme j'étais à bout d'idées, ne sachant plus quelle dépendance supprimer, j'ai eu une idée : mettre en cache les requêtes. En gros, l'utilisateur va charger toutes les chunks mais seulement une fois. Les prochaines fois, ces chunks seront prises directement sur son appareil au lieu d'être téléchargées.
Dans ce post, je vous explique comment je m'y suis pris en utilisant les Service Workers. C'est aussi une occasion pour ceux qui n'ont jamais rencontré concept d'en apprendre un peu plus.
C'est quoi un service worker ?
Un service worker c'est simplement un fichier javascript (ou typescirpt) qui fonctionne en arrière-plan (pas sur la thread principale). Il te permet de faire quelques trucs magiques comme :
- Intercepter des requêtes
- Recevoir et propager des notifications
- Synchroniser avec un serveur
- Faire des PWA et des applications web qui peuvent fonctionner offline
Pour mon besoin, c'est l'interception des requêtes qui m'a été utile et c'est donc sur elle que je vais m'appesantir.
Créer un Service Worker
Comme je vous l'ai dit, un service worker c'est un fichier javascript ou typescript. Et le code que vous allez y écrire n'aura rien de nouveau. C'est du javascript ou du typescript que vous écrivez tous les jours. Mais pour vous éviter des maux de tête inutile, préférez toujours un fichier javascript (si vous êtes dans un projet typescript, assurez-vous que les fichiers .js sont pris en compte et correctement gérés).
On va donc créer ce fichier à la racine de notre projet. TOUJOURS A LA RACINE ! Pourquoi ? Parce qu'on veut qu'il intercepte toutes les requêtes de notre application web. Pour cela, il doit être juste en dessous de notre origine. Si vous le mettez dans des sous-dossiers, la configuration risquera de vous donner des migraines.
Une fois que vous avez votre fichier sw.js ou peu importe ce que vous l'aurez nommé, il faudra maintenant dire à votre application : hey man, j'ai un service worker, est-ce que tu peux l'utiliser ?
javascriptAvec ce bout de code, vous venez d'enregistrer votre service worker. Pour le voir en action (sur Chrome), ouvrez votre console développeur et allez dans la section Application, ensuite dans Service Workers. Vous devriez avoir quelque chose qui ressemble à ceci :

Chouette ! Maintenant, ouvrez votre service worker et voici ce que vous allez écrire. Je vous expliquerai dans les commentaires et après le block de code.
javascriptL'essentiel des explications est dans les commentaires. Cependant, voici quelques points intéressants sur lesquels j'aimerais insister :
- event.waitUntil est une fonction qui reçoit une promesse. Aussi longtemps que cette promesse ne sera pas résolue, l'installation ou l'activation ne se fera pas. Et si jamais elle n'est pas résolue avec succès, alors l'installation ou l'activation échoueront.
- event.respondWith aussi reçoit une promesse. Cette promesse contient la réponse à présenter au client. Elle peut venir du cache, d'un serveur ou même fabriquée dans le service worker
- Par souci de simplification, je stocke tous les fichiers dans un seul cache (global-app-cache-1). Pour une meilleure gestion, ça serait mieux d'avoir un cache pour les images, les fonts, les chunks, ... Mais aussi, dans une vraie application, vous aurez besoin de catégoriser les requêtes avant de décider s'il faut chercher dans le cache ou aller directement chercher sur un serveur ou même fabriquer dans le service worker. Par exemple, les requêtes pour obtenir le contenu qui vient de Sanity (au moins pour l'instant) et les requêtes vers Firebase, je les laisse directement passer et je ne cache pas leurs réponses.
- Les service workers n'ont pas accès au DOM. Cela veut dire que vous ne pouvez pas sélectionner des choses sur une page, par exemple.
- Le problème avec le caching, c'est qu'il faut gérer manuellement le cache pour supprimer le vieux contenu et avoir du contenu frais. Bien qu'en ajoutant le caching, je viens de gagner en performance et en rapidité de chargement, je continue à avoir le vieux contenu mis en cache alors que j'ai déjà mis à jour mon post sur Sanity. Ça reste à arranger (ma première tâche pour demain 😂) !
En conclusion
J'ai essayé mon blog sur mobile, je me suis rendu compte qu'il était sensiblement un peu plus rapide que d'habitude. Dès que j'ai visité une route, elle est stockée en cache et les prochaines fois, j'y vais très rapidement.

