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
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
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.
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.
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.
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.
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.
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é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.