Web hors-ligne : From scratch vs Workbox
Disclaimer :
Cet article est le sixième de la série d’articles sur le web hors-ligne et les services workers. Sommaire :
Web hors-ligne : l'alliance entre l'optimisation utilisateur et les pratiques éco-responsables
Web hors ligne : Précacher votre application pour un usage hors ligne dégradé avec des fallback
Web hors-ligne : Stratégies de cache du plus green au plus simple, entre offline first et online first
Web hors-ligne : Stale While Revalidate ou le meilleur de l’UX pour le pire de l’écoresponsabilité
Web hors-ligne : Des métriques positives pour l’utilisateur comme pour la planète
Introduction : Développer une PWA, oui ! Mais avec quoi ?
Le développement des Progressive Web Apps (PWA) a révolutionné la manière dont nous utilisons le Web. Ces applications combinent les avantages des sites web et des applications natives, offrant aux utilisateurs une expérience riche, fluide et accessible, même hors ligne. Développer une PWA from scratch est possible, mais implique une gestion manuelle du cache, des stratégies de mise en cache, de l'interception des événements réseau. Cela nécessite de solides bases en Javascript et une compréhension approfondie des service workers (SW), ce qui peut s'avérer complexe et chronophage. Et c’est là qu’intervient Workbox.
Workbox : la boîte à outils spécial SW de Google
Faciliter l’accès aux services workers
Workbox est une boîte à outils JavaScript open-source qui simplifie la création et le déploiement de services workers, des scripts qui gèrent le cache des ressources, interceptent les requêtes réseau et étendent les fonctionnalités hors ligne de vos PWAs. En utilisant Workbox, vous bénéficiez d'un ensemble de solutions pré-configurées pour gérer les aspects clés d'une PWA :
- Gestion du cache: Workbox implémente différentes stratégies de mise en cache (pré-cacher les données type CSS/JS/HTML/images, cache uniquement lorsqu'il y a une connexion réseau, cache uniquement lorsque l'utilisateur est hors ligne, etc.).
- Mise à jour du cache: Workbox permet de mettre à jour le contenu en cache en utilisant des schémas de mise à jour (mise à jour fréquente pour les données sensibles, mise à jour plus rare pour le contenu statique).
- Interception des événements réseau: Workbox intercepte les requêtes réseau pour les gérer de manière optimale en utilisant des stratégies de réponse.
- Gestion des erreurs : Workbox gère les erreurs de réseau et les problèmes de cache pour une meilleure stabilité de votre PWA.
Cette librairie offre une approche plus simple, efficace et performante pour développer des PWAs. De plus, même en installant tous les packages (workbox-sw, workbox-recipes, …), le poids global de l’installation ne dépasse pas 18,3 ko ce qui a un impact négligeable sur la performance de l’application.
Implémentation d’un SW dans un fichier séparé
Dans cette série consacrée aux services workers, nous avons opté pour le from scratch pour tous nos exemples de code afin de bien maîtriser les différents concepts mis en avant par les services workers (stratégies de cache, fallback…). Maintenant, il est intéressant de voir cette librairie en action en reprenant les mêmes fonctionnalités évoquées dans les articles précédents afin de voir en quoi Workbox apporte son petit plus.
Dans notre script sw.js, on commence toujours par importer le CDN qui va nous permettre de récupérer les différentes méthodes des différents modules (routing, strategies, recipes…). On retrouve aussi à chaque fois les étapes d’installation et d’activation du service worker.
importScripts( 'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);
self.addEventListener('install', (event) => {
event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim());
});
Gestion du cache en Online first
/* Import du script */
const {NetworkFirst} = workbox.strategies;
const networkFirst = new NetworkFirst();
/* Étapes d'install et d'activate */
self.addEventListener('fetch', async (event) => {
const request = event.request;
event.respondWith(networkFirst.handle({event, request}));
});
Offline Fallback en Online first
/* Import du script */
const {setDefaultHandler} = workbox.routing
const {NetworkFirst} = workbox.strategies
const {offlineFallback} = workbox.recipes;
/* Étapes d'install et d'activate */
setDefaultHandler(new NetworkFirst());
offlineFallback();
Stale While Revalidate en Offline First
/* Import du script */
const {setDefaultHandler} = workbox.routing
const {CacheFirst, StaleWhileRevalidate} = workbox.strategies
const staleWhileRevalidate = new StaleWhileRevalidate();
setDefaultHandler(new CacheFirst());
/* Étapes d'install et d'activate */
self.addEventListener('fetch', async (event) => {
const request = event.request;
event.respondWith(staleWhileRevalidate.handle({event, request}));
});
Vous pouvez retrouver ces exemples de code dans le dépôt du POC suivant : https://github.com/CametDean/sw-workbox
Implémentation d’un SW dans le fichier de configuration
Créer un service worker dans un fichier que l’on place dans notre dossier public est une bonne méthode, mais ce n’est pas l’unique méthode. Il est aussi possible d’intégrer directement dans le fichier de configuration de notre application le service worker avec ses différentes stratégies de cache grâce à la librairie Vite PWA ou Webpack Inject Manifest.
Gestion du cache en Online first
Voici un exemple d’implémentation du cache en mode online first :
d’abord dans le fichier sw.js
/* Import du script */
const {NetworkFirst} = workbox.strategies;
const networkFirst = new NetworkFirst();
/* Étapes d'install et d'activate */
self.addEventListener('fetch', async (event) => {
const request = event.request;
event.respondWith(networkFirst.handle({event, request}));
});
puis son équivalent dans le fichier vite.config.ts
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
runtimeCaching: [
{
urlPattern: /^https:\/\/pwa-cms\.ln1\.eu\/api/,
handler: 'NetworkFirst',
},
],
},
Ce qui est intéressant avec la librairie, c’est qu’elle permet de simplifier encore plus le paramétrage du service worker en ajoutant le nombre de stratégies de cache en fonction de nos besoins et en ajustant les options dans chaque pattern de stratégie.
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
runtimeCaching: [
{
urlPattern: /^https:\/\/pwa-cms\.ln1\.eu\/api/,
handler: 'NetworkFirst',
options: {
cacheName: 'api-cache',
networkTimeoutSeconds: 5,
cacheableResponse: {
statuses: [0, 200],
},
},
},
{
urlPattern: /^https:\/\/pwa-cms\.ln1\.eu.*\.(png|jpg|jpeg|svg|gif)$/,
handler: 'CacheFirst',
options: {
cacheName: 'image-cache',
cacheableResponse: {
statuses: [0, 200],
},
expiration: {
maxEntries: 100,
maxAgeSeconds: 30 * 24 * 60 * 60,
},
},
},
],
},
Dans cet exemple, nous pouvons voir que deux stratégies de cache sont définies :
- Le Network First est utilisé pour les résultats de notre api : notre urlPattern contient notre endpoint et dans les options sont définis le nom du cache, le temps que le service worker va attendre avant d’afficher la dernière version du cache ainsi que le paramètre qui détermine ce qui rend une réponse cacheable ou non (ici, seulement les requêtes aux statuts 0 et 200 seront cachées).
- Le Cache First, lui, va être utilisé pour les résultats de notre api concernant les images uniquement comme l’indique urlPattern. On remarque également qu’une notion d’expiration du cache a été ajoutée dans les options. Ici, au maximum 100 images seront stockées et pour une durée de 30 jours.
Quand privilégier le développement from scratch ?
Comparer les scénarios
Bien que Workbox offre de nombreux avantages, il existe des scénarios où son utilisation peut ne pas être appropriée. Voici quelques exemples :
- Applications simples : Si votre PWA ne nécessite pas de stratégies de cache complexes ou de fonctionnalités avancées, vous pouvez probablement développer une PWA sans Workbox ou avec l’inject manifest.
- Applications qui ne nécessitent pas de mode hors ligne : Si votre PWA ne nécessite pas d'être accessible hors ligne, vous n'avez pas besoin d'utiliser Workbox pour gérer le cache.
- Applications qui utilisent déjà un framework de gestion de cache : Si votre framework de développement web inclut déjà un système de gestion de cache, vous n'avez peut-être pas besoin d'utiliser Workbox.
- Cas complexe sur mesure : vous pouvez utiliser Workbox mais cela vous demandera de développer un plugin sur mesure qui peut être plus complexe que d’utiliser votre service worker développé from scratch.
Dans de tels cas, le surcroît de complexité apporté par l'outil pourrait être superflu.
Conclusion
En conclusion, le choix d'utiliser ou non Workbox lors du développement d'une PWA dépend des besoins spécifiques du projet. Alors que Workbox offre une variété d'avantages en termes de gestion du cache, de tests et de performance, il est crucial de considérer attentivement si ses fonctionnalités correspondent aux exigences de l'application web en question. En comprenant les différences entre développer une PWA avec et sans Workbox, les développeurs peuvent prendre des décisions éclairées pour optimiser l'expérience utilisateur et la fonctionnalité de leurs applications.