Actif

L'un des aspects clés des progressive web apps est leur fiabilité, ils peuvent charger des éléments rapidement, maintenir l'engagement des utilisateurs et fournir des retours immédiats, même lorsque les conditions du réseau sont mauvaises. Comment est-ce possible ? Grâce à l'événement fetch du service worker.

L'événement de récupération

Navigateurs pris en charge

  • Chrome: 40 <ph type="x-smartling-placeholder">
  • Edge: 17 <ph type="x-smartling-placeholder">
  • Firefox: 44 <ph type="x-smartling-placeholder">
  • Safari: 11.1. <ph type="x-smartling-placeholder">

Source

L'événement fetch nous permet d'intercepter chaque requête réseau effectuée par la PWA dans le champ d'application du service worker, pour les requêtes d'origine identique ou multi-origine. En plus des demandes de navigation et d'éléments, l'extraction d'un service worker installé permet d'afficher les visites de pages après le premier chargement d'un site sans appel réseau.

Le gestionnaire fetch reçoit toutes les requêtes d'une application, y compris les URL et les en-têtes HTTP, et laisse le développeur de l'application décider de la manière de les traiter.

Le service worker se situe entre le client et le réseau.

Votre service worker peut transférer une requête au réseau, répondre à l'aide d'une réponse précédemment mise en cache ou créer une réponse. À vous de choisir. Prenons un exemple simple :

self.addEventListener("fetch", event => {
    console.log(`URL requested: ${event.request.url}`);
});

Répondre à une demande

Lorsqu'une requête parvient à votre service worker, vous pouvez effectuer deux opérations : vous pouvez l'ignorer, ce qui lui permet d'aller sur le réseau, ou vous pouvez y répondre. En répondant aux requêtes depuis votre service worker, vous choisissez quels éléments sont renvoyés à votre PWA et comment ils sont renvoyés à votre PWA, même lorsque l'utilisateur est hors connexion.

Pour répondre à une requête entrante, appelez event.respondWith() à partir d'un gestionnaire d'événements fetch, comme ceci:

// fetch event handler in your service worker file
self.addEventListener("fetch", event => {
    const response = .... // a response or a Promise of response
    event.respondWith(response);
});

Vous devez appeler respondWith() de manière synchrone et renvoyer un objet Response. Toutefois, vous ne pouvez pas appeler respondWith() une fois que le gestionnaire d'événements d'extraction a terminé, comme dans un appel asynchrone. Si vous devez attendre la réponse complète, vous pouvez transmettre une promesse à respondWith() qui se résout en renvoyant une réponse.

Créer des réponses

Grâce à l'API Fetch, vous pouvez créer des réponses HTTP dans votre code JavaScript. Ces réponses peuvent être mises en cache à l'aide de l'API Cache Storage et renvoyées comme si elles provenaient d'un serveur Web.

Pour créer une réponse, créez un objet Response en définissant son corps et des options telles que l'état et les en-têtes:

const simpleResponse = new Response("Body of the HTTP response");

const options = {
   status: 200,
   headers: {
    'Content-type': 'text/html'
   }
};
const htmlResponse = new Response("<b>HTML</b> content", options)

Répondre à partir du cache

Maintenant que vous savez comment diffuser des réponses HTTP à partir d'un service worker, il est temps d'utiliser l'interface de stockage en cache pour stocker des éléments sur l'appareil.

Vous pouvez utiliser l'API de stockage en cache pour vérifier si la requête reçue de la PWA est disponible dans le cache et, le cas échéant, l'utiliser pour répondre à respondWith(). Pour ce faire, vous devez d'abord effectuer une recherche dans le cache. La fonction match(), disponible dans l'interface caches de premier niveau, recherche tous les magasins de votre origine ou sur un seul objet de cache ouvert.

La fonction match() reçoit une requête HTTP ou une URL en tant qu'argument, et renvoie une promesse qui se résout avec la réponse associée à la clé correspondante.

// Global search on all caches in the current origin
caches.match(urlOrRequest).then(response => {
   console.log(response ? response : "It's not in the cache");
});

// Cache-specific search
caches.open("pwa-assets").then(cache => {
  cache.match(urlOrRequest).then(response => {
    console.log(response ? response : "It's not in the cache");
  });
});

Stratégies de mise en cache

La diffusion de fichiers uniquement à partir du cache du navigateur ne convient pas à tous les cas d'utilisation. Par exemple, l'utilisateur ou le navigateur peut vider le cache. C'est pourquoi vous devez définir vos propres stratégies de livraison d'assets pour votre PWA. Vous n'êtes pas limité à une seule stratégie de mise en cache. Vous pouvez en définir plusieurs en fonction des formats d'URL. Par exemple, vous pouvez avoir une stratégie pour le nombre minimal de composants d'interface utilisateur, une autre pour les appels d'API et une troisième pour les URL d'image et de données. Pour ce faire, lisez event.request.url dans ServiceWorkerGlobalScope.onfetch, puis analysez-le à l'aide d'expressions régulières ou d'un format d'URL. (Au moment de la rédaction de ce document, le format d'URL n'est pas compatible avec toutes les plates-formes.)

Voici les stratégies les plus courantes:

Cache d'abord
Recherche d'abord une réponse mise en cache, puis revient au réseau si aucune réponse n'est trouvée.
Priorité au réseau
Demande d'abord une réponse au réseau. Si aucune réponse n'est renvoyée, recherche la réponse dans le cache.
Obsolète pendant la revalidation
Diffuse une réponse à partir du cache, tandis qu'une application en arrière-plan demande la dernière version et l'enregistre dans le cache pour la prochaine requête de l'élément.
Réseau uniquement
Il répond toujours par une réponse du réseau ou par des erreurs. Le cache n'est jamais consulté.
Cache uniquement
Répondez toujours avec une réponse du cache ou des erreurs. Le réseau ne sera jamais consulté. Les éléments qui seront diffusés à l'aide de cette stratégie doivent être ajoutés au cache avant d'être demandés.

Mettre en cache d'abord

Avec cette stratégie, le service worker recherche la requête correspondante dans le cache et renvoie la réponse correspondante si elle est mise en cache. Sinon, il récupère la réponse à partir du réseau (éventuellement, en mettant à jour le cache pour les futurs appels). S'il n'y a ni réponse de cache ni réponse du réseau, la requête génère une erreur. Étant donné que la diffusion des assets sans passer par le réseau a tendance à être plus rapide, cette stratégie donne la priorité aux performances par rapport à l'actualisation.

Stratégie &quot;Cache First&quot;

self.addEventListener("fetch", event => {
   event.respondWith(
     caches.match(event.request)
     .then(cachedResponse => {
       // It can update the cache to serve updated content on the next request
         return cachedResponse || fetch(event.request);
     }
   )
  )
});

Priorité au réseau

Cette stratégie est le miroir de la stratégie Cache First. il vérifie si la demande peut être satisfaite à partir du réseau et, si ce n’est pas possible, essaie de la récupérer à partir du cache. Comme le cache d'abord. S'il n'y a ni réponse du réseau, ni réponse du cache, la requête génère une erreur. La réponse du réseau est généralement plus lente que la réponse du cache, car cette stratégie donne la priorité au contenu mis à jour plutôt qu'aux performances.

Stratégie Network First

self.addEventListener("fetch", event => {
   event.respondWith(
     fetch(event.request)
     .catch(error => {
       return caches.match(event.request) ;
     })
   );
});

Obsolète pendant la revalidation

Cette stratégie non actualisée renvoie immédiatement une réponse mise en cache, puis recherche une mise à jour sur le réseau et remplace la réponse mise en cache le cas échéant. Cette stratégie effectue toujours une requête réseau, car même si une ressource mise en cache est trouvée, elle essaie de mettre à jour le cache avec les données reçues du réseau, afin d'utiliser la version mise à jour dans la requête suivante. Cette stratégie vous permet donc de bénéficier de la diffusion rapide de la stratégie "premier cache" et de mettre à jour le cache en arrière-plan.

Stratégie non actualisée lors de la revalidation de la stratégie

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(cachedResponse => {
        const networkFetch = fetch(event.request).then(response => {
          // update the cache with a clone of the network response
          const responseClone = response.clone()
          caches.open(url.searchParams.get('name')).then(cache => {
            cache.put(event.request, responseClone)
          })
          return response
        }).catch(function (reason) {
          console.error('ServiceWorker fetch failed: ', reason)
        })
        // prioritize cached response over network
        return cachedResponse || networkFetch
      }
    )
  )
})

Réseau uniquement

La stratégie "Réseau uniquement" est semblable à la façon dont les navigateurs se comportent sans service worker ni API Cache Storage. Les requêtes ne renvoient une ressource que si elle peut être extraite du réseau. Cela est souvent utile pour des ressources telles que les requêtes API uniquement en ligne.

Stratégie &quot;Réseau uniquement&quot;

Cache uniquement

La stratégie de mise en cache uniquement garantit que les requêtes n'atteignent jamais le réseau. toutes les requêtes entrantes sont traitées avec un élément de cache prérempli. Le code suivant utilise le gestionnaire d'événements fetch avec la méthode match du stockage en cache pour répondre uniquement au cache:

self.addEventListener("fetch", event => {
   event.respondWith(caches.match(event.request));
});

Stratégie de mise en cache uniquement.

Stratégies personnalisées

Bien que les stratégies ci-dessus soient courantes de mise en cache, c'est vous qui êtes responsable de votre service worker et de la manière dont les requêtes sont traitées. Si aucune de ces solutions ne correspond à vos besoins, créez-en une.

Par exemple, vous pouvez utiliser une stratégie axée sur le réseau avec un délai avant expiration pour prioriser le contenu mis à jour, mais uniquement si la réponse apparaît dans un seuil que vous avez défini. Vous pouvez également fusionner une réponse mise en cache avec une réponse réseau et créer une réponse complexe à partir du service worker.

Mise à jour des composants...

Il peut être difficile de maintenir à jour les éléments mis en cache de vos PWA. Bien que la stratégie obsolète de revalidation soit un moyen d'y parvenir, elle n'est pas la seule. Dans le chapitre Mettre à jour, vous découvrirez différentes techniques pour mettre à jour le contenu et les éléments de votre application.

Ressources