Optimisation des pré-chargements avec prefetch, dns-prefetch et prerender

Astuce par (Alsacréations, Strasbourg)
Créé le (16673 lectures)
Tags : dns, prerender, prefetch

Les navigateurs rivalisent d'ingéniosité pour diminuer le temps de chargement des pages, ou du moins le faire ressentir à l'utilisateur. Quelques tentatives de pré-chargement automatique furent réalisées dans le passé, sans toutefois rencontrer un succès immédiat. En effet, effectuer une requête nécessite de "deviner" par avance quelles pages seront les plus pertinentes à pré-charger, avec plus ou moins de justesse et de risques :

  • cela consomme de la bande passante - peut-être inutilement si le visiteur décide de ne pas continuer sa navigation dans le sens de l'anticipation
  • cela consomme des ressources locales (mémoire vive, disque dur, etc)
  • cela peut fausser les statistiques du serveur si elles n'ignorent pas ces requêtes

Désormais, des moteurs de navigateurs courants tels que Firefox, Internet Explorer 9/10/11+ et Chrome peuvent exploiter les directives de la balise <link> et de l'attribut rel (relation) avec certains mots-clés pour pré-charger des URLs précises, que ce soit du code HTML, CSS, JavaScript, images, etc.

Ces techniques sont à utiliser avec une extrême précaution. Mal employées, elles peuvent vous causer plus de tort que de bien et gêner vos utilisateurs (voir les différents cas évoqués précédemment).

Prefetch

Une relation prefetch va déclencher le pré-chargement du fichier mentionné par le lien (attribut href), afin de le placer en cache.

Cette instruction figure dans la spécification côté WhatWG (Links) et W3C (HTML5 Links). Elle est supportée par Mozilla Firefox, Chrome et IE9+.

<link rel="prefetch" href="http://www.mondomaine.com/autre_page.html">
<link rel="prefetch" href="http://www.mondomaine.com/autre_feuille_de_styles.css">

On ne peut pas spécifier d'adresse globale de répertoire, de caractère joker (*), de fichier à télécharger/enregistrer, ou d'autre protocole que http/https. Ne passons pas à côté des choses simples.

Il faut se servir de cette directive avec parcimonie pour ne pas pénaliser la bande passante du visiteur (qui est peut-être sur du bas-débit/mobile) et du serveur. De toute manière, les navigateurs imposent des limites ; par exemple Internet Explorer 11 ne tolère que 10 ressources pré-chargées.

Quand utiliser prefetch ?

Lorsque la navigation logique de l'utilisateur a toutes les chances d'aboutir sur un lien précis, par exemple :

  • Lorsqu'il consulte une suite de pages (présentation, slideshow, slides, résultats de recherche paginés...) et qu'il y a une forte probabilité qu'il passe à la suivante.
  • Pour anticiper des images ou des feuilles de styles qui auront toutes les chances de s'afficher sur les pages principales du site, ou de l'application web.

Tests et vérifications

Comment distinguer une requête envoyée au serveur pour un pré-chargement d'une consultation réelle ? Le navigateur peut le signaler avec un en-tête HTTP supplémentaire. Par exemple Firefox envoie X-moz: prefetch, qui pourra se retrouver avec PHP dans $_SERVER['HTTP_X_MOZ'] mais ceci peut évoluer au cours du temps et n'est pas standardisé.

Tous les bons outils de développement (Firebug, F12, etc) pourront afficher les requêtes partant vers le serveur.

La spécification précise également que l'on peut placer cette relation avec les éléments <link>, <a> et <area>.

Dns-prefetch

Dans ce cas, le pré-chargement sera en réalité une requête DNS menée par anticipation, pour résoudre un nom de domaine en adresse IP, sans attendre de le rencontrer dans le code source de la page ou d'une page suivante. Ces requêtes peuvent parfois nécessiter quelques dizaines de millisecondes, et il y en a d'autant plus qu'un document fait appel à des ressources issues de domaines variés.

Note : Cette instruction n'est pas encore standardisée. Elle est reconnue par Mozilla Firefox, Google Chrome et IE10+.

<link rel="dns-prefetch" href="http://www.autredomaine.com/">

Ou sans protocole :

<link rel="dns-prefetch" href="//www.autredomaine.com/">

Si l'on sait par avance que www.mondomaine.com fera ultérieurement appel à des pages, images, CSS, JavaScript de www.autredomaine.com, ou de cdn.mondomaine.com, il pourra être utile de tenter de prédire ce comportement et de gagner du temps sur les requêtes DNS qui seront nécessaires pour convertir ces différents domaines ou sous-domaines en adresses IP (entre 50 et 250 ms généralement).

Certains navigateurs - notamment Chrome - utilisent aussi cette fonctionnalité sans vous demander votre avis et sans déclaration explicite dans un code HTML ; par exemple selon l'historique de l'utilisateur (les 10 derniers domaines visités avant fermeture) et/ou par diviniation de ce qu'il va taper dans la barre d'adresse. Pour voir quelques statistiques DNS sur ce moteur, consultez la page chrome://dns/

Prerender

Le pré-rendu de document va passer la main au moteur d'interprétation pour mettre en cache (mémoire) par avance une page afin de l'afficher quasiment instantanément si le visiteur y accède en ayant déjà un "rendu graphique".

Note : Cette instruction n'est pas encore standardisée. Elle est reconnue par Google Chrome et IE11+.

<link rel="prerender" href="http://www.mondomaine.com/autre_page.html">

Dans ce cas de figure, l'API PageVisibility pourra être utile pour se renseigner sur l'état précis du rendu de la page avec la propriété document.visibilityState (alors égale à prerender). On peut ajouter dans la valeur de l'attribut rel le mot-clé prefetch pour les navigateurs le supportant mais pas encore prerender.

Pour citer un exemple, Internet Explorer 11+ ne pré-calcule qu'une page à la fois. Il agit aussi intelligemment en n'exécutant cette instruction que si le document y faisant appel est au premier plan (onglet actif) et visible. La page de destination est effacée de la mémoire, entre autres :

  • si le visiteur décide de diriger ses clics vers une autre URL
  • s'il n'y accède pas dans un délai de 5 minutes
  • s'il change de fenêtre/onglet actif
  • si l'adresse renvoie une erreur HTTP (famille des 400, 500, etc)
  • si la page destination utilise <audio> ou <video>

On retrouve ces conditions du côté de Google Chrome, qui y ajoutera aussi une annulation en cas de :

  • demande d'identification HTTP ou de page HTTPS
  • création de popup
  • ressources système trop occupées
  • requête AJAX (XMLHttpRequest) avec méthode PUT/POST/DELETE
  • navigation privée

Ce navigateur permet d'examiner l'activité du pre-rendering via la page interne chrome://net-internals/#prerender. Il n'y a (a priori) pas d'en-tête HTTP spécifique envoyé donc pas de possibilité de distinguer un prerender d'une requête classique.

Chrome prerender

Un petit site de test a été mis au point sur http://prerender-test.appspot.com/ pour détecter l'activation (ou non) de cette fonctionnalité.

Il faut retenir qu'on peut aussi injecter ce type de balise avec JavaScript, de préférence dans la section <head>, c'est alors la dernière présente qui prendra le pas sur les autres.

Ressources

Commentaires

Manumanu a dit le

Merci, je me suis mis au prefetch ! :)