Architecture des Progressive Web Apps : Patrons de Service Worker JavaScript | MLOG | MLOG

4. Réseau uniquement (Network-Only)

La stratégie "network-only" (réseau uniquement) récupère toujours les ressources depuis le réseau, en contournant complètement le cache. Cette stratégie est utilisée lorsque vous avez absolument besoin de la dernière version d'une ressource et que la mise en cache n'est pas souhaitée.

Exemple :

            
self.addEventListener('fetch', event => {
  event.respondWith(
    fetch(event.request)
  );
});

            

5. Obsolète pendant la revalidation (Stale-While-Revalidate)

La stratégie "stale-while-revalidate" sert immédiatement la ressource en cache tout en récupérant simultanément la dernière version depuis le réseau. Une fois la requête réseau terminée, le cache est mis à jour avec la nouvelle version. Cette stratégie offre une réponse initiale rapide tout en garantissant que l'utilisateur reçoit finalement le contenu le plus à jour. C'est une stratégie utile pour le contenu non critique qui bénéficie de la vitesse plutôt que de la fraîcheur absolue.

Exemple :

            
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        const fetchPromise = fetch(event.request).then(networkResponse => {
          caches.open('my-cache').then(cache => {
            cache.put(event.request, networkResponse.clone());
            return networkResponse;
          });
        });
        return response || fetchPromise;
      })
  );
});

            

6. Cache, puis réseau (Cache, then Network)

Similaire à "stale-while-revalidate" mais sans le retour immédiat de la ressource en cache. Elle vérifie d'abord le cache, et ce n'est que si la ressource est présente que la requête réseau se poursuivra en arrière-plan pour mettre à jour le cache.

Choisir la bonne stratégie de mise en cache

La stratégie de mise en cache optimale dépend des exigences spécifiques de votre application. Prenez en compte des facteurs tels que :

En sélectionnant soigneusement les stratégies de mise en cache appropriées, vous pouvez améliorer considérablement les performances et l'expérience utilisateur de votre PWA, même dans des environnements hors ligne. Des outils comme Workbox ([https://developers.google.com/web/tools/workbox](https://developers.google.com/web/tools/workbox)) peuvent simplifier la mise en œuvre de ces stratégies.

Synchronisation en arrière-plan : Gérer les mutations hors ligne

La synchronisation en arrière-plan permet à votre PWA d'effectuer des tâches en arrière-plan, même lorsque l'utilisateur est hors ligne. Ceci est particulièrement utile pour gérer les soumissions de formulaires, les mises à jour de données et autres opérations nécessitant une connectivité réseau. L'API `BackgroundSyncManager` vous permet d'enregistrer des tâches qui seront exécutées lorsque le réseau sera disponible.

Enregistrer une tâche de synchronisation en arrière-plan

Pour enregistrer une tâche de synchronisation en arrière-plan, vous devez utiliser la méthode `register` du `BackgroundSyncManager`. Cette méthode prend un nom de balise (tag) unique en argument. Le nom de la balise identifie la tâche spécifique à effectuer.

Exemple :

            
self.addEventListener('sync', event => {
  if (event.tag === 'my-sync-task') {
    event.waitUntil(doSomeWork());
  }
});

            

Gérer l'événement de synchronisation (sync)

Lorsque le navigateur détecte une connectivité réseau, il envoie un événement `sync` au service worker. Vous pouvez écouter cet événement et effectuer les actions nécessaires, comme l'envoi de données au serveur.

Exemple :

            
async function doSomeWork() {
  // Récupérer les données depuis IndexedDB
  const data = await getDataFromIndexedDB();

  // Envoyer les données au serveur
  try {
    const response = await fetch('/api/sync', {
      method: 'POST',
      body: JSON.stringify(data),
      headers: {
        'Content-Type': 'application/json'
      }
    });

    if (response.ok) {
      // Effacer les données d'IndexedDB
      await clearDataFromIndexedDB();
    } else {
      // Gérer les erreurs
      console.error('La synchronisation a échoué :', response.status);
      throw new Error('La synchronisation a échoué');
    }
  } catch (error) {
    // Gérer les erreurs réseau
    console.error('Erreur réseau :', error);
    throw error;
  }
}

            

Exemple : Soumission de formulaire hors ligne

Imaginez un scénario où un utilisateur remplit un formulaire en étant hors ligne. Le service worker peut stocker les données du formulaire dans IndexedDB et enregistrer une tâche de synchronisation en arrière-plan. Lorsque le réseau devient disponible, le service worker récupérera les données du formulaire depuis IndexedDB et les soumettra au serveur.

  1. L'utilisateur remplit le formulaire et clique sur soumettre en étant hors ligne.
  2. Les données du formulaire sont stockées dans IndexedDB.
  3. Une tâche de synchronisation en arrière-plan est enregistrée avec une balise unique (par ex., `form-submission`).
  4. Lorsque le réseau est disponible, l'événement `sync` est déclenché.
  5. Le service worker récupère les données du formulaire depuis IndexedDB et les soumet au serveur.
  6. Si la soumission réussit, les données du formulaire sont supprimées d'IndexedDB.

Notifications Push : Engager les utilisateurs avec des mises Ă  jour opportunes

Les notifications push permettent à votre PWA d'envoyer des mises à jour et des messages opportuns aux utilisateurs, même lorsque l'application n'est pas activement exécutée dans le navigateur. Cela peut améliorer considérablement l'engagement et la rétention des utilisateurs. L'API Push et l'API Notifications fonctionnent ensemble pour livrer les notifications push.

S'abonner aux notifications Push

Pour recevoir des notifications push, les utilisateurs doivent d'abord donner leur autorisation Ă  votre PWA. Vous pouvez utiliser l'API `PushManager` pour abonner les utilisateurs aux notifications push.

Exemple :

            
navigator.serviceWorker.ready.then(registration => {
  registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: 'YOUR_PUBLIC_VAPID_KEY'
  })
  .then(subscription => {
    // Envoyer les détails de l'abonnement à votre serveur
    sendSubscriptionToServer(subscription);
  })
  .catch(error => {
    console.error('Échec de l\'abonnement :', error);
  });
});

            

Important : Remplacez `YOUR_PUBLIC_VAPID_KEY` par votre véritable clé VAPID (Voluntary Application Server Identification). Les clés VAPID sont utilisées pour identifier votre serveur d'application et garantir que les notifications push sont envoyées de manière sécurisée.

Gérer les notifications Push

Lorsqu'une notification push est reçue, le service worker envoie un événement `push`. Vous pouvez écouter cet événement et afficher la notification à l'utilisateur.

Exemple :

            
self.addEventListener('push', event => {
  const payload = event.data ? event.data.text() : 'Aucun contenu';

  event.waitUntil(
    self.registration.showNotification('Ma PWA', {
      body: payload,
      icon: 'icon.png'
    })
  );
});

            

Personnaliser les notifications Push

L'API Notifications vous permet de personnaliser l'apparence et le comportement des notifications push. Vous pouvez spécifier le titre, le corps, l'icône, le badge et d'autres options.

Exemple :

            
self.addEventListener('push', event => {
  const data = event.data.json();
  const title = data.title || 'Ma PWA';
  const options = {
    body: data.body || 'Aucun message',
    icon: data.icon || 'icon.png',
    badge: data.badge || 'badge.png',
    vibrate: [200, 100, 200],
    data: { // Données personnalisées accessibles au clic sur la notification
      url: data.url || '/'
    },
    actions: [
      {action: 'explore', title: 'Explorer ce nouveau monde',
        icon: 'images/checkmark.png'},
      {action: 'close', title: 'Fermer',
        icon: 'images/xmark.png'},
    ]
  };

  event.waitUntil(self.registration.showNotification(title, options));
});


self.addEventListener('notificationclick', function(event) {
  event.notification.close();

  // Vérifier si l'utilisateur a cliqué sur une action.
  if (event.action === 'explore') {
    clients.openWindow(event.notification.data.url);
  } else {
    // Action par défaut : ouvrir l'application.
    clients.openWindow('/');
  }
});

            

Exemple : Alerte d'actualité

Une application d'actualités peut utiliser les notifications push pour alerter les utilisateurs des dernières nouvelles. Lorsqu'un nouvel article est publié, le serveur envoie une notification push à l'appareil de l'utilisateur, affichant un bref résumé de l'article. L'utilisateur peut alors cliquer sur la notification pour ouvrir l'article complet dans la PWA.

Patrons avancés de Service Worker

1. Analytique hors ligne

Suivez le comportement des utilisateurs même lorsqu'ils sont hors ligne en stockant les données analytiques localement et en les envoyant au serveur lorsque le réseau est disponible. Cela peut être réalisé en utilisant IndexedDB et la synchronisation en arrière-plan (Background Sync).

2. Gestion des versions et mises Ă  jour

Mettez en œuvre une stratégie de gestion de versions robuste pour votre service worker afin de garantir que les utilisateurs reçoivent toujours les dernières mises à jour sans perturber leur expérience. Utilisez des techniques de "cache busting" pour invalider les anciennes ressources mises en cache.

3. Service Workers modulaires

Organisez votre code de service worker en modules pour améliorer la maintenabilité et la lisibilité. Utilisez les modules JavaScript (ESM) ou un empaqueteur de modules comme Webpack ou Rollup.

4. Mise en cache dynamique

Mettez en cache les ressources dynamiquement en fonction des interactions et des modèles d'utilisation des utilisateurs. Cela peut aider à optimiser la taille du cache et à améliorer les performances.

Meilleures pratiques pour le développement de Service Worker

Conclusion

Les service workers JavaScript sont des outils puissants pour créer des PWA robustes, performantes et engageantes. En comprenant le cycle de vie du service worker et en mettant en œuvre des stratégies de mise en cache, de synchronisation en arrière-plan et de notifications push appropriées, vous pouvez créer des expériences utilisateur exceptionnelles, même dans des environnements hors ligne. Cet article a exploré les principaux patrons de service worker et les meilleures pratiques pour vous guider dans la création de PWA réussies pour un public mondial. À mesure que le web continue d'évoluer, les service workers joueront un rôle de plus en plus important dans l'avenir du développement web.

N'oubliez pas d'adapter ces patrons aux exigences spécifiques de votre application et de toujours donner la priorité à l'expérience utilisateur. En adoptant la puissance des service workers, vous pouvez créer des PWA qui sont non seulement fonctionnelles mais aussi agréables à utiliser, quel que soit l'emplacement ou la connexion réseau de l'utilisateur.

Ressources supplémentaires :