Types de liens : preload

La valeur preload de l'attribut rel de l'élément <link> permet de déclarer des requêtes à récupérer dans la partie <head> du HTML de la page, en spécifiant les ressources dont votre page va avoir besoin dans peu de temps, et qu'il serait souhaitable de charger le plus tôt possible, avant que le rendu de la page par le navigateur ne commence. Cela permet de s'assurer que les ressources sont disponibles plus tôt et qu'elles auront moins de chances de bloquer le rendu de la page, ce qui améliore les performances.

Les bases

Pour charger un fichier CSS permettant de styler une page, on utilise le plus souvent l'élément <link> de la manière suivante :

html
<link rel="stylesheet" href="styles/main.css" />

Ici, nous allons utiliser la valeur preload sur l'attribut rel, ce qui transformera l'élément <link> en outil de préchargement utilisable pour n'importe quelle ressource. Nous devrons aussi indiquer :

  • le chemin de la ressource dans l'attribut href ;
  • le type de ressource dans l'attribut as ;

Voici un exemple simple (voir nos fichiers JS et CSS d'exemple et le résultat obtenu) :

html
<head>
  <meta charset="utf-8" />
  <title>Exemple de préchargement JS et CSS</title>

  <link rel="preload" href="style.css" as="style" />
  <link rel="preload" href="main.js" as="script" />

  <link rel="stylesheet" href="style.css" />
</head>

<body>
  <h1>Balles rebondissantes</h1>
  <canvas></canvas>

  <script src="main.js" defer></script>
</body>

Dans l'exemple ci-dessus, nous préchargeons nos fichiers CSS et JavaScript afin qu'ils puissent être disponibles dès qu'ils sont nécessaires pour le rendu de la page. Cet exemple est trivial, car le navigateur va probablement découvrir en même temps les balises de préchargement, le <link rel="stylesheet"> et le <script>, mais le bénéfice sera bien plus visible si les ressources sont plus nombreuses, plus lourdes et chargées à différents endroits. Par exemple :

  • les ressources qui sont chargées depuis un fichier CSS, comme certaines polices et images ;
  • les ressources inclues par des fichiers JavaScript, comme des fichiers JSON, d'autres scripts importés ou des services web ;
  • les fichiers image et vidéos plus importants.

preload dispose aussi d'autres avantages. L'utilisation de l'attribut as pour spécifier le type de contenu à précharger permet au navigateur de :

  • prioriser les ressources se chargeant avec davantage de précision ;
  • les stocker dans le cache pour de futures requêtes, ce qui permet de réutiliser les ressources si c'est pertinent ;
  • appliquer la bonne stratégie de sécurité du contenu aux ressources ;
  • mettre en place les bons en-têtes de requêtes Accept pour les ressources.

Quels types de contenu peuvent être préchargés ?

De nombreux différents types de contenu peuvent être préchargés. Les valeurs possibles de l'attribut as sont les suivantes :

  • audio : fichier audio, typiquement intégré avec l'élément <audio> ;
  • document : un document HTML destiné à être embarqué dans une <frame> ou dans une <iframe> ;
  • embed : une ressource à embarquer dans un élément <embed> ;
  • fetch : une ressource accessible via une requête fetch ou XHR, comme un ArrayBuffer ou un fichier JSON ;
  • font : un fichier de police ;
  • image : un fichier image ;
  • object : une ressource à embarquer à l'intérieur d'un élément <object> ;
  • script : un fichier JavaScript ;
  • style : une feuille de styles CSS ;
  • track : un fichier WebVTT ;
  • worker : un web worker JavaScript ou un worker partagé ;
  • video : un fichier vidéo, typiquement intégré avec l'élément <video>.

Note : le préchargement de l'élément video est inclut dans la spécification Preload mais n'est pas encore implémenté par les navigateurs.

Note : pour davantage de détails sur ces valeurs et sur la façon dont la spécification Preload prévoit de les traiter, consultez link element extensions (en anglais). Notez également que la liste complète des valeurs acceptées par l'attribut as est déterminé par la spécification Fetch — voir la spécification request destinations (en anglais).

Inclure un type MIME

Les éléments <link> peuvent accepter un attribut type, contenant le type MIME de la ressource vers laquelle pointe le document. Ceci est tout spécialement utile lorsque l'on effectue un préchargement des ressources – le navigateur utilisera alors l'attribut type pour vérifier s'il prend en charge la ressource et la télécharger si c'est le cas, ou l'ignorer dans le cas contraire.

Vous pouvez voir un exemple de ce fonctionnement dans notre vidéo d'exemple (voir le code source complet ou la version exécutable en direct), utilisant le bout de code proposé ci-dessous. À noter que si ce code ne lancera pas de préchargement effectif sur aucun navigateur – le préchargement des vidéos n'est encore implémenté sur aucun navigateur – cela permet d'illustrer le fonctionnement général du préchargement.

html
<head>
  <meta charset="utf-8" />
  <title>Exemple de préchargement de vidéo</title>

  <link rel="preload" href="sintel-short.mp4" as="video" type="video/mp4" />
</head>
<body>
  <video controls>
    <source src="sintel-short.mp4" type="video/mp4" />
    <source src="sintel-short.webm" type="video/webm" />
    <p>
      Votre navigateur ne prend pas en charge les vidéos HTML5. Voici un
      <a href="sintel-short.mp4">lien vers le fichier vidéo en remplacement</a>.
    </p>
  </video>
</body>

Le code de l'exemple ci-dessus permet le préchargement de la video/mp4 uniquement sur les navigateurs qui prennent en charge cette fonctionnalité et pour les personnes ayant un navigateur prenant en charge le format video/mp4 (car ce format est le premier élément <source> spécifié). Cela devrait rendre le lecteur vidéo plus ergonomique et plus responsive pour ces personnes.

Concernant les personnes disposant d'un navigateur prenant en charge tout aussi bien les formats video/mp4 et video/webm support, il est important de noter que si un élément <link rel="preload" href="sintel-short.webm" as="video" type="video/webm"> est aussi spécifié, alors les deux formats video/mp4 et video/webm seront préchargés — même si un seul d'entre eux est utilisé.

En conclusion, il est déconseillé de précharger de multiple formats pour la même ressource. La bonne pratique est plutôt de précharger uniquement le type de média qu'utilise la majorité des personnes qui visitent votre site. C'est pourquoi le code fourni en exemple ne précharge pas la vidéo au format video/webm.

Cependant, l'absence de préchargement n'empêche pas la vidéo video/webm d'être utilisée par les personnes qui en ont besoin : pour les navigateurs qui ne prennent pas en charge le format video/mp4 mais qui prennent en charge le format video/webm alors le code de l'exemple permettra toujours d'utiliser la vidéo au format video/webm — cela évitera simplement de précharger inutilement une ressource pour la plupart des navigateurs.

Récupération de l'activation du CORS

Lors du préchargement des ressources analysées par des fonctions activant le CORS (partage des ressources entre origines multiples), comme par exemple fetch(), XMLHttpRequest ou fonts), une attention particulière doit être portée à la mise en place de l'attribut crossorigin sur l'élément <link>. L'attribut à besoin d'être mis en place pour faire correspondre le CORS de la ressource et le mode d'identification, même s'il ne s'agit pas d'une ressource ayant une origine différente de celle de la page.

Comme mentionné ci-dessus, un cas de figure intéressant est celui qui s'applique aux fichiers de polices. Pour plusieurs raisons, celles-ci doivent être analysées en utilisant le mode anonyme du CORS (voir cet article en anglais : Font fetching requirements).

Voici un cas d'utilisation. Vous trouverez le code source complet sur GitHub ainsi qu'une démonstration :

html
<head>
  <meta charset="utf-8" />
  <title>Exemple de préchargement de police Web</title>

  <link
    rel="preload"
    href="fonts/cicle_fina-webfont.woff2"
    as="font"
    type="font/woff2"
    crossorigin />
  <link
    rel="preload"
    href="fonts/zantroke-webfont.woff2"
    as="font"
    type="font/woff2"
    crossorigin />

  <link href="style.css" rel="stylesheet" />
</head>
<body></body>

En plus de fournir un type MIME avec l'attribut type, ce code utilise un attribut crossorigin afin de s'assurer que le préchargement du CORS correspond à la requête de chargement de la police.

Inclure des médias

Une autre belle fonctionnalité de l'élément <link> concerne leur capacité à accepter les attributs media. Il peut accepter les requêtes de types de médias ou encore des media queries complètes, ce qui vous permet de faire du préchargement responsive !

Voici un exemple. Vous pouvez consulter son code source sur GitHub ou étudier un exemple de démonstration :

html
<head>
  <meta charset="utf-8" />
  <title>Exemple de préchargement responsive</title>

  <link
    rel="preload"
    href="bg-image-narrow.png"
    as="image"
    media="(max-width: 600px)" />
  <link
    rel="preload"
    href="bg-image-wide.png"
    as="image"
    media="(min-width: 601px)" />

  <link rel="stylesheet" href="main.css" />
</head>
<body>
  <header>
    <h1>Mon site</h1>
  </header>

  <script>
    var mediaQueryList = window.matchMedia("(max-width: 600px)");
    var header = document.querySelector("header");

    if (mediaQueryList.matches) {
      header.style.backgroundImage = "url(bg-image-narrow.png)";
    } else {
      header.style.backgroundImage = "url(bg-image-wide.png)";
    }
  </script>
</body>

Dans cet exemple nous incluons les attributs media dans notre élément <link> pour qu'une image plus fine soit préchargée si la personne visitant le site dispose d'un écran plus petit, et pour qu'une image plus large soit chargée sur les écrans plus larges. Pour cela, nous utilisons Window.matchMedia et MediaQueryList (en-US) (consultez la page Tester les requêtes média en JavaScript pour en savoir plus).

Cela augmente les chances que la police sera disponible lors du rendu de la page, et diminue les risques de FOUT (pour flash of unstyled text, soit « flash de texte sans mis en forme » en français).

Il sera dommage de limiter le préchargement aux images, voyez plus loin ! On pourrait imaginer de précharger l'affichage d'un diagramme SVG si le visiteur se trouve sur un petit écran avec une bande passante ou une disponibilité CPU plus limitée, ou encore de précharger des morceaux de JavaScript complexes utilisés pour faire fonctionner une modélisation 3D interactive uniquement si les ressources du visiteur sont suffisantes.

Scripts et préchargement

Une autre fonctionnalité notable est la possibilité d'exécuter le préchargement à l'aide d'un script. Par exemple, voici la création d'une instance HTMLLinkElement (en-US) qui est ensuite attachée au DOM :

js
var preloadLink = document.createElement("link");
preloadLink.href = "myscript.js";
preloadLink.rel = "preload";
preloadLink.as = "script";
document.head.appendChild(preloadLink);

Cela signifie que le navigateur va précharger le fichier myscript.js, mais ne va pas réellement l'utiliser directement. Pour l'utiliser, vous pouvez faire ceci :

js
var preloadedScript = document.createElement("script");
preloadedScript.src = "myscript.js";
document.body.appendChild(preloadedScript);

C'est utile lorsque vous voulez précharger un script mais repousser son exécution au moment exact où vous en avez réellement besoin.

Autres ressources concernant les mécanismes de préchargement

D'autres fonctionnalités de préchargement sont disponibles, mais sachez qu'aucune d'entre elle n'est aussi adaptée à l'objectif recherché que <link rel="preload">. En voici la liste :

  • <link rel="prefetch"> est pris en charge depuis quelque temps par les navigateurs, mais est destinée à la récupération préalable des ressources qui vont être utilisées lors de la prochaine page visitée/chargée (par exemple lorsque vous vous rendrez sur une autre page du site). C'est une bonne chose, mais ce n'est pas utile pour la page en cours de chargement ! Par ailleurs, les navigateurs donnent une priorité plus faible à prefetch qu'à preload — la page courante est prioritaire par rapport à la page suivante. Consultez la FAQ sur le préchargement des liens pour plus de détails ;
  • <link rel="prerender"> effectue le rendu une page spécifiée en arrière-plan, ce qui permet d'accélerer son chargement si la personne visitant le site se rend sur cette page par la suite. Du fait du gaspillage potentiel de bande passante pour les visiteurs (on charge des éléments sans savoir si on en aura besoin), Chrome traite l'instruction prerender comme une instruction NoState prefetch ;
  • <link rel="subresource"> Non-standard était pris en charge par Chrome il y a quelques temps et était destiné à gérer la même chose que preload, mais il y avait un problème : il n'y avait aucun moyen de définir une priorité sur les éléments à charger (as n'existait pas encore), donc toutes les ressources étaient chargées avec la même priorité (la plus faible) ;
  • Il y a un grand nombre de scripts de chargements de ressources disponibles un peu partout, mais aucun ne peut avoir la puissance d'une file de priorisation gérée directement par le navigateur. De plus, ces scripts sont sujets à des problèmes de performances similaires.

Spécifications

Specification
HTML Standard
# link-type-preload

Compatibilité des navigateurs

BCD tables only load in the browser

Voir aussi

  • Preload: What Is It Good For? par Yoav Weiss (en anglais)