Gérer les requêtes de navigation

Répondez aux requêtes de navigation sans attendre le réseau en utilisant un service worker.

Les requêtes de navigation sont des requêtes de documents HTML effectuées par votre navigateur chaque fois que vous saisissez une nouvelle URL dans la barre de navigation ou que vous suivez un lien sur une page qui vous redirige vers une nouvelle URL. C'est là que les service workers ont le plus d'impact sur les performances : si vous utilisez un service worker pour répondre aux requêtes de navigation sans attendre le réseau, vous pouvez vous assurer que les navigations sont rapides et fiables, en plus d'être résilientes lorsque le réseau n'est pas disponible. Il s'agit du principal gain de performances d'un service worker par rapport à ce qui est possible avec la mise en cache HTTP.

Comme indiqué dans le guide Identifier les ressources chargées à partir du réseau, une requête de navigation est la première d'une série de requêtes potentiellement nombreuses effectuées dans la "cascade" du trafic réseau. Le code HTML que vous chargez via une requête de navigation lance le flux de toutes les autres requêtes de sous-ressources telles que les images, les scripts et les styles.

Dans le gestionnaire d'événements fetch d'un service worker, vous pouvez déterminer si une requête est une navigation en vérifiant la propriété request.mode sur FetchEvent. Si elle est définie sur 'navigate', il s'agit d'une requête de navigation.

En règle générale, n'utilisez pas de Cache-Control headers de longue durée pour mettre en cache la réponse HTML d'une requête de navigation. Elles doivent normalement être satisfaites via le réseau, avec Cache-Control: no-cache, pour s'assurer que le code HTML, ainsi que la chaîne de requêtes réseau ultérieures, sont (raisonnablement) récents. Malheureusement, interroger le réseau chaque fois que l'utilisateur accède à une nouvelle page signifie que chaque navigation peut être lente. Au minimum, cela signifie qu'il ne sera pas toujours rapide.

Différentes approches pour les architectures

Il peut être difficile de déterminer comment répondre aux requêtes de navigation tout en évitant le réseau. L'approche appropriée dépend en grande partie de l'architecture de votre site Web et du nombre d'URL uniques auxquelles les utilisateurs peuvent accéder.

Bien qu'il n'existe pas de solution universelle, les consignes générales suivantes devraient vous aider à déterminer l'approche la plus viable.

Petits sites statiques

Si votre application Web se compose d'un nombre relativement faible (par exemple, quelques dizaines) d'URL uniques, et que chacune de ces URL correspond à un fichier HTML statique différent, une approche viable consiste à mettre en cache tous ces fichiers HTML et à répondre aux requêtes de navigation avec le code HTML mis en cache approprié.

La mise en cache préalable vous permet de mettre en cache le code HTML à l'avance, dès que le service worker est installé, et de mettre à jour le code HTML mis en cache chaque fois que vous recompilez votre site et redéployez votre service worker.

Si vous préférez éviter de pré-mettre en cache l'intégralité de votre code HTML (par exemple, parce que les utilisateurs ont tendance à ne naviguer que vers un sous-ensemble d'URL de votre site), vous pouvez utiliser une stratégie de mise en cache d'exécution stale-while-revalidate. Toutefois, soyez prudent avec cette approche, car chaque document HTML est mis en cache et mis à jour séparément. L'utilisation de la mise en cache de l'environnement d'exécution pour le code HTML est plus appropriée si vous disposez d'un petit nombre d'URL qui sont fréquemment consultées par le même ensemble d'utilisateurs, et si vous êtes à l'aise avec le fait que ces URL soient revalidées indépendamment les unes des autres.

Applications monopages

Les applications Web modernes utilisent fréquemment une architecture à page unique. Dans ce cas, le code JavaScript côté client modifie le code HTML en réponse aux actions de l'utilisateur. Ce modèle utilise l'API History pour modifier l'URL actuelle lorsque l'utilisateur interagit avec l'application Web, ce qui entraîne une navigation "simulée". Bien que les navigations suivantes puissent être "fausses", la navigation initiale est réelle, et il est toujours important de s'assurer qu'elle n'est pas bloquée sur le réseau.

Heureusement, si vous utilisez l'architecture monopage, il existe un modèle simple à suivre pour diffuser la navigation initiale à partir du cache : le shell d'application. Dans ce modèle, votre service worker répond aux requêtes de navigation en renvoyant le même fichier HTML unique qui a déjà été pré-mis en cache, quelle que soit l'URL demandée. Ce code HTML doit être minimaliste et se composer, par exemple, d'un indicateur de chargement générique ou d'un contenu squelette. Une fois que le navigateur a chargé ce code HTML à partir du cache, votre code JavaScript côté client existant prend le relais et affiche le contenu HTML correct pour l'URL de la requête de navigation d'origine.

Workbox fournit les outils dont vous avez besoin pour mettre en œuvre cette approche. navigateFallback option vous permet de spécifier le document HTML à utiliser comme shell d'application, ainsi qu'une liste d'autorisation et de refus facultative pour limiter ce comportement à un sous-ensemble de vos URL.

Applications multipages

Si votre serveur Web génère le code HTML de votre site de manière dynamique ou si vous avez plus de quelques dizaines de pages uniques, il est beaucoup plus difficile d'éviter le réseau lors du traitement des requêtes de navigation. Les conseils de la section Tout le reste s'appliquent probablement à vous.

Toutefois, pour un certain sous-ensemble d'applications multipages, vous pouvez implémenter un service worker qui réplique entièrement la logique utilisée dans votre serveur Web pour générer du code HTML. Cette approche fonctionne mieux si vous pouvez partager les informations de routage et de création de modèles entre les environnements du serveur et du service worker, et en particulier si votre serveur Web utilise JavaScript (sans s'appuyer sur des fonctionnalités spécifiques à Node.js, comme l'accès au système de fichiers).

Si votre serveur Web appartient à cette catégorie et que vous souhaitez explorer une approche permettant de déplacer la génération de code HTML hors du réseau et dans votre service worker, les conseils de l'article Au-delà des SPA : architectures alternatives pour votre PWA peuvent vous aider à vous lancer.

Tout le reste

Si vous ne pouvez pas répondre aux requêtes de navigation avec du code HTML mis en cache, vous devez prendre des mesures pour vous assurer que l'ajout d'un service worker à votre site (pour gérer d'autres requêtes non HTML) ne ralentit pas vos navigations. Le démarrage du service worker sans l'utiliser pour répondre à une requête de navigation entraîne une légère latence (comme expliqué dans Créer des applications plus rapides et plus résilientes avec un service worker). Vous pouvez limiter ce temps de traitement en activant une fonctionnalité appelée préchargement de la navigation, puis en utilisant la réponse réseau qui a été préchargée dans votre gestionnaire d'événements fetch.

Workbox fournit une bibliothèque d'assistance qui détecte si le préchargement de la navigation est compatible et, le cas échéant, simplifie le processus d'envoi d'instructions au service worker pour qu'il utilise la réponse du réseau.