Deux méthodes de préchargement : balises <link> et en-têtes HTTP

Demián Renzulli
Demián Renzulli

Dans cet atelier de programmation, vous allez implémenter le préchargement de deux manières : avec <link rel="prefetch"> et avec l'en-tête HTTP Link.

L'application exemple est un site Web qui comporte une page de destination promotionnelle avec une remise spéciale sur le t-shirt le plus vendu de la boutique. Étant donné que la page de destination renvoie à un seul produit, on peut supposer qu'un pourcentage élevé d'utilisateurs accéderont à la page d'informations détaillées sur le produit. La page produit est donc un excellent candidat pour la prélecture sur la page de destination.

Évaluer les performances

Commencez par établir les performances de référence :

  1. Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
  2. Cliquez sur l'onglet Réseau.

  3. Dans la liste déroulante Limitation du débit, sélectionnez 3G rapide pour simuler un type de connexion lente.

  4. Pour charger la page du produit, cliquez sur Acheter maintenant dans l'application exemple.

Le chargement de la page product-details.html prend environ 600 ms :

Panneau &quot;Réseau&quot; affichant les temps de chargement de product-details.html

Pour améliorer la navigation, insérez une balise prefetch dans la page de destination afin de précharger la page product-details.html :

  • Ajoutez l'élément <link> suivant à l'en-tête du fichier views/index.html :
<!doctype html>
  <html>
    <head>
       <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">

      <link rel="prefetch" href="/product-details.html" as="document">
      ...
</head>

L'attribut as est facultatif, mais recommandé. Il aide le navigateur à définir les bons en-têtes et à déterminer si la ressource se trouve déjà dans le cache. Voici quelques exemples de valeurs pour cet attribut : document, script, style, font, image et autres.

Pour vérifier que la prélecture fonctionne :

  1. Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
  2. Cliquez sur l'onglet Réseau.

  3. Dans la liste déroulante Limitation du débit, sélectionnez 3G rapide pour simuler un type de connexion lente.

  4. Décochez la case "Désactiver le cache".

  5. Actualisez l'application.

Désormais, lorsque la page de destination se charge, la page product-details.html se charge également, mais avec la priorité la plus basse :

Panneau &quot;Réseau&quot; montrant le fichier product-details.html préchargé.

La page est conservée dans le cache HTTP pendant cinq minutes, après quoi les règles Cache-Control normales s'appliquent au document. Dans ce cas, product-details.html comporte un en-tête cache-control avec une valeur de public, max-age=0, ce qui signifie que la page est conservée pendant cinq minutes au total.

Réévaluer les performances

  1. Actualisez l'application.
  2. Pour charger la page du produit, cliquez sur Acheter maintenant dans l'application exemple.

Examinez le panneau Réseau. Il existe deux différences par rapport à la trace réseau initiale :

  • La colonne Taille indique "cache de préchargement", ce qui signifie que cette ressource a été récupérée à partir du cache du navigateur plutôt que du réseau.
  • La colonne Time (Temps) indique que le temps de chargement du document est désormais d'environ 10 ms.

Cela représente une réduction d'environ 98 % par rapport à la version précédente, qui prenait environ 600 ms.

Panneau &quot;Réseau&quot; affichant product-details.html récupéré à partir du cache de préchargement.

Bonus : utiliser prefetch comme amélioration progressive

Le préchargement est idéalement implémenté en tant qu'amélioration progressive pour les utilisateurs qui naviguent avec des connexions rapides. Vous pouvez utiliser l'API Network Information pour vérifier les conditions du réseau et, en fonction de celles-ci, injecter dynamiquement des balises de préchargement. Vous pouvez ainsi minimiser la consommation de données et réduire les coûts pour les utilisateurs disposant de forfaits de données lents ou coûteux.

Pour implémenter la prélecture adaptative, commencez par supprimer le tag <link rel="prefetch"> de views/index.html :

<!doctype html>
  <html>
    <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
       <link rel="prefetch" href="/product-details.html" as="document">
       ...
    </head>

Ajoutez ensuite le code suivant à public/script.js pour déclarer une fonction qui injecte dynamiquement la balise prefetch lorsque l'utilisateur dispose d'une connexion rapide :

function injectLinkPrefetchIn4g(url) {
    if (window.navigator.connection.effectiveType === '4g') {
        //generate link prefetch tag
        const linkTag = document.createElement('link');
        linkTag.rel = 'prefetch';
        linkTag.href = url;
        linkTag.as = 'document';

        //inject tag in the head of the document
        document.head.appendChild(linkTag);
    }
}

Voici comment fonctionne cette fonction :

  • Elle vérifie la propriété effectiveType de l'API Network Information pour déterminer si l'utilisateur dispose d'une connexion 4G (ou plus rapide).
  • Si cette condition est remplie, il génère une balise <link> avec prefetch comme type d'indice, transmet l'URL qui sera préchargée dans l'attribut href et indique que la ressource est un document HTML dans l'attribut as.
  • Enfin, il injecte le script de manière dynamique dans le head de la page.

Ajoutez ensuite script.js à views/index.html, juste avant la balise de fermeture </body> :

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

Demander script.js à la fin de la page permet de s'assurer qu'il sera chargé et exécuté après l'analyse et le chargement de la page.

Pour vous assurer que la prélecture n'interfère pas avec les ressources critiques de la page actuelle, ajoutez l'extrait de code suivant pour appeler injectLinkPrefetchIn4g() sur l'événement window.load :

<body>
      ...
      <script src="/script.js"></script>
      <script>
           window.addEventListener('load', () => {
                injectLinkPrefetchIn4g('/product-details.html');
           });
      </script>
</body>

La page de destination précharge désormais product-details.html uniquement sur les connexions rapides. Pour vérifier que :

  1. Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
  2. Cliquez sur l'onglet Réseau.
  3. Dans la liste déroulante Limitation du débit, sélectionnez En ligne.
  4. Actualisez l'application.

Vous devriez voir product-details.html dans le panneau "Réseau" :

Panneau &quot;Réseau&quot; montrant le fichier product-details.html préchargé.

Pour vérifier que la page produit n'est pas préchargée sur les connexions lentes :

  1. Dans la liste déroulante "Throttling" (Limitation du débit), sélectionnez Slow 3G (3G lente).
  2. Actualisez l'application.

Le panneau Réseau ne doit inclure que les ressources de la page de destination sans product-details.html :

Panneau &quot;Réseau&quot; montrant que product-details.html n&#39;est pas préchargé.

L'en-tête HTTP Link peut être utilisé pour précharger le même type de ressources que la balise link. Le choix de l'une ou l'autre dépend principalement de vos préférences, car la différence de performances est insignifiante. Dans ce cas, vous l'utiliserez pour précharger le CSS principal de la page produit, afin d'améliorer encore son rendu.

Ajoutez un en-tête HTTP Link pour style-product.css dans la réponse du serveur pour la page de destination :

  1. Ouvrez le fichier server.js et recherchez le gestionnaire get() pour l'URL racine : /.
  2. Ajoutez la ligne suivante au début du gestionnaire :
app.get('/', function(request, response) {
    response.set('Link', '</style-product.css>; rel=prefetch');
    response.sendFile(__dirname + '/views/index.html');
});
  1. Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
  2. Cliquez sur l'onglet Réseau.
  3. Actualisez l'application.

Le style-product.css est désormais préchargé avec la priorité la plus faible après le chargement de la page de destination :

Panneau &quot;Réseau&quot; affichant le fichier style-product.css préchargé.

Pour accéder à la page du produit, cliquez sur Acheter maintenant. Examinez le panneau Réseau :

Panneau &quot;Réseau&quot; affichant le fichier style-product.css récupéré à partir du cache de préchargement.

Le fichier style-product.css est récupéré à partir du "cache de préchargement" et n'a mis que 12 ms à se charger.