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 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".
<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.
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.
Commentaires
Merci, je me suis mis au prefetch ! :)