Optimiser le code JavaScript tiers

Les scripts tiers ont un impact sur les performances. C'est pourquoi il est important de les auditer régulièrement et d'utiliser des techniques efficaces pour les charger. Cet atelier de programmation vous explique comment optimiser le chargement des ressources tierces. Il aborde les techniques suivantes:

  • Différer le chargement du script

  • Ressources non critiques à chargement différé

  • Se connecter préalablement aux origines requises

L'application exemple incluse comprend une page Web simple avec trois fonctionnalités provenant de sources tierces:

  • Intégration d'une vidéo

  • Bibliothèque de visualisation de données pour le rendu d'un graphique linéaire

  • Un widget de partage sur les réseaux sociaux

Capture d'écran de la page avec les ressources tierces mises en surbrillance.
Ressources tierces dans l'application exemple.

Vous allez commencer par mesurer les performances de l'application, puis appliquer chaque technique pour améliorer différents aspects de ses performances.

Évaluer les performances

Commencez par ouvrir l'application exemple en mode plein écran:

  1. Cliquez sur Remix to Edit (Remixer pour modifier) pour rendre le projet modifiable.
  2. Pour prévisualiser le site, appuyez sur Afficher l'application, puis sur Plein écran plein écran.

Exécutez un audit de performances Lighthouse sur la page pour établir des 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 Lighthouse.
  3. Cliquez sur Mobile.
  4. Cochez la case Performances. (Vous pouvez décocher les autres cases de la section "Audits".
  5. Cliquez sur Simulation 3G rapide, ralentissement du processeur 4x.
  6. Cochez la case Vider l'espace de stockage.
  7. Cliquez sur Exécuter des audits.

Lorsque vous exécutez un audit sur votre machine, les résultats exacts peuvent varier. Toutefois, notez que la durée de la phase First Contentful Paint (FCP) est assez élevée et que Lighthouse suggère deux possibilités d'investigation: Éliminer les ressources qui bloquent l'affichage et Préconnexion aux origines requises. (Même si toutes les métriques sont affichées en vert, les optimisations continueront à donner lieu à des améliorations.)

Capture d'écran de l'audit Lighthouse montrant un FCP de 2,4 secondes et deux opportunités: Éliminer les ressources qui bloquent l'affichage et Préconnexion aux origines requises.

Reporter le code JavaScript tiers

L'audit Éliminer les ressources qui bloquent l'affichage a déterminé que vous pourriez gagner du temps en différant un script provenant de d3js.org:

Capture d'écran de l'audit "Éliminer les ressources qui bloquent l'affichage", avec le script d3.v3.min.js mis en évidence

D3.js est une bibliothèque JavaScript permettant de créer des visualisations de données. Le fichier script.js de l'application exemple utilise des fonctions utilitaires D3 pour créer le graphique en courbes SVG et l'ajouter à la page. L'ordre des opérations est important ici: script.js doit s'exécuter après l'analyse du document et le chargement de la bibliothèque D3. C'est pourquoi elle est incluse juste avant la balise </body> fermante dans index.html.

Toutefois, le script D3 est inclus dans le <head> de la page, ce qui bloque l'analyse du reste du document:

Capture d&#39;écran du fichier index.html avec le tag de script en surbrillance dans l&#39;en-tête.

Deux attributs magiques peuvent débloquer l'analyseur lorsqu'il est ajouté au tag de script:

  • async garantit que les scripts sont téléchargés en arrière-plan et s'exécutent à la première occasion une fois le téléchargement terminé.

  • defer garantit que les scripts sont téléchargés en arrière-plan et s'exécutent une fois l'analyse terminée.

Étant donné que ce graphique n'est pas vraiment essentiel à l'ensemble de la page et qu'il sera probablement en dessous de la ligne de flottaison, utilisez defer pour vous assurer que l'analyseur n'est pas bloqué.

Étape 1: Chargez le script de manière asynchrone avec l'attribut defer

À la ligne 17 de index.html, ajoutez l'attribut defer à l'élément <script>:

<script src="https://d3js.org/d3.v3.min.js" defer></script>

Étape 2: Vérifiez le bon ordre des opérations

Maintenant que D3 est différé, script.js s'exécutera avant que D3 ne soit prêt, ce qui entraînera une erreur.

Les scripts avec l'attribut defer s'exécutent dans l'ordre dans lequel ils ont été spécifiés. Pour vous assurer que script.js est exécuté une fois que D3 est prêt, ajoutez-y defer et déplacez-le jusqu'à la <head> du document, juste après l'élément <script> D3. Désormais, il ne bloque plus l'analyseur et le téléchargement commence plus tôt.

<script src="https://d3js.org/d3.v3.min.js" defer></script>
<script src="./script.js" defer></script>

Chargement différé des ressources tierces

Toutes les ressources situées en dessous de la ligne de flottaison sont adaptées au chargement différé.

L'application exemple comprend une vidéo YouTube intégrée dans un iframe. Pour connaître le nombre de requêtes envoyées par la page et lesquelles proviennent de l'iFrame YouTube intégré:

  1. Pour prévisualiser le site, appuyez sur Afficher l'application, puis sur Plein écran plein écran.
  2. Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
  3. Cliquez sur l'onglet Réseau.
  4. Cochez la case Désactiver le cache.
  5. Sélectionnez 3G rapide dans le menu déroulant Limitation.
  6. Actualisez la page.

Capture d&#39;écran du panneau DevTools Network.

Le panneau Network (Réseau) indique que la page a effectué un total de 28 requêtes et transféré près de 1 Mo de ressources compressées.

Pour identifier les demandes envoyées par le iframe YouTube, recherchez l'ID vidéo 6lfaiXM6waw dans la colonne Initiateur. Pour regrouper toutes les requêtes par domaine:

  • Dans le panneau Réseau, effectuez un clic droit sur le titre d'une colonne.

  • Dans le menu déroulant, sélectionnez la colonne Domains (Domaines).

  • Pour trier les demandes par domaine, cliquez sur le titre de la colonne Domaines.

Le nouveau tri révèle que des demandes supplémentaires ont été envoyées aux domaines Google. Au total, l'iFrame YouTube envoie 14 demandes de scripts, de feuilles de style, d'images et de polices. Toutefois, à moins que les utilisateurs ne fassent défiler la page pour lire la vidéo, ils n'ont pas vraiment besoin de tous ces éléments.

En attendant le chargement différé de la vidéo jusqu'à ce que l'utilisateur accède à la section correspondante de la page, vous réduisez le nombre de demandes initiales. Cette approche permet d'économiser les données des utilisateurs et d'accélérer le chargement initial.

Pour implémenter le chargement différé, vous pouvez utiliser l'Intersection Observer, une API de navigateur qui vous avertit lorsqu'un élément entre ou quitte la fenêtre d'affichage du navigateur.

Étape 1: Empêcher le chargement initial de la vidéo

Pour charger l'iFrame vidéo de manière différée, vous devez d'abord empêcher son chargement habituel. Pour ce faire, remplacez l'attribut src par l'attribut data-src afin d'indiquer l'URL de la vidéo:

<iframe width="560" height="315" data-src="https://www.youtube.com/embed/lS9D6w1GzGY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

data-src est un attribut de données, qui vous permet de stocker des informations supplémentaires sur les éléments HTML standards. Vous pouvez nommer n'importe quel attribut de données, à condition qu'il commence par "data-".

Un iFrame sans src ne se charge tout simplement pas.

Étape 2: Utilisez l'outil Intersection Observer pour effectuer un chargement différé de la vidéo

Pour charger la vidéo lorsque l'utilisateur fait défiler la page jusqu'à elle, vous devez savoir quand cela se produit. C'est là qu'intervient l'API Intersection Observer. L'API Intersection Observer vous permet d'enregistrer une fonction de rappel qui s'exécute chaque fois qu'un élément que vous souhaitez suivre entre dans la fenêtre d'affichage ou en sort.

Pour commencer, créez un fichier et nommez-le lazy-load.js:

  • Cliquez sur New File (Nouveau fichier) et attribuez-lui un nom.
  • Cliquez sur Ajouter ce fichier.

Ajoutez le tag de script à l'en-tête de votre document:

 <script src="/lazy-load.js" defer></script>

Dans lazy-load.js, créez un IntersectionObserver et transmettez-lui une fonction de rappel à exécuter:

// create a new Intersection Observer
let observer = new IntersectionObserver(callback);

Attribuez maintenant à observer un élément cible à surveiller (l'iFrame vidéo, dans ce cas) en le transmettant en tant qu'argument dans la méthode observe:

// the element that you want to watch
const element = document.querySelector('iframe');

// register the element with the observe method
observer.observe(element);

callback reçoit une liste d'objets IntersectionObserverEntry et l'objet IntersectionObserver lui-même. Chaque entrée contient un élément target et des propriétés qui décrivent ses dimensions, sa position, l'heure à laquelle il est entré dans la fenêtre d'affichage, etc. L'une des propriétés de IntersectionObserverEntry est isIntersecting, c'est-à-dire une valeur booléenne égale à true lorsque l'élément entre dans la fenêtre d'affichage.

Dans cet exemple, target correspond à iframe. isIntersecting est égal à true lorsque target entre dans la fenêtre d'affichage. Pour observer son fonctionnement, remplacez callback par la fonction suivante:

let observer = new IntersectionObserver(callback);
let observer = new IntersectionObserver(function(entries, observer) {
    entries.forEach(entry => {
      console.log(entry.target);
      console.log(entry.isIntersecting);
    });
  });
  1. Pour prévisualiser le site, appuyez sur Afficher l'application, puis sur Plein écran plein écran.
  2. Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
  3. Cliquez sur l'onglet Console.

Essayez de faire défiler l'écran vers le haut ou vers le bas. Vous devriez voir la valeur de isIntersecting changer et l'élément cible enregistré dans la console.

Pour charger la vidéo lorsque l'utilisateur fait défiler la page jusqu'à sa position, utilisez isIntersecting comme condition pour exécuter une fonction loadElement, qui récupère la valeur de l'élément data-src de l'élément iframe et la définit comme attribut src de l'élément iframe. Ce remplacement déclenche le chargement de la vidéo. Ensuite, une fois la vidéo chargée, appelez la méthode unobserve sur observer pour arrêter de regarder l'élément cible:

let observer = new IntersectionObserver(function (entries, observer) {
  entries.forEach(entry => {
    console.log(entry.target);
    console.log(entry.isIntersecting);
  });
});
    if (entry.isIntersecting) {
      // do this when the element enters the viewport
      loadElement(entry.target);
      // stop watching
      observer.unobserve(entry.target);
    }
  });
});

function loadElement(element) {
  const src = element.getAttribute('data-src');
  element.src = src;
}

Étape 3: Réévaluez les performances

Pour voir comment la taille et le nombre de ressources ont changé, ouvrez le panneau Network (Réseau) des outils de développement, puis actualisez à nouveau la page. Le panneau Network (Réseau) indique que la page a généré 14 requêtes et seulement 260 Ko. C'est une amélioration significative !

Maintenant, faites défiler la page et gardez un œil sur le panneau Network (Réseau). Lorsque vous arrivez à la vidéo, vous devriez voir la page déclencher des demandes supplémentaires.

Connexion préalable aux origines requises

Vous avez différé le code JavaScript non critique et chargé les requêtes YouTube de manière différée. Le moment est donc venu d'optimiser le contenu tiers restant.

L'ajout de l'attribut rel=preconnect à un lien indique au navigateur d'établir une connexion avec un domaine avant que la demande de ressource ne soit effectuée. Il est préférable d'utiliser cet attribut pour les origines qui fournissent les ressources dont la page a vraiment besoin.

L'audit Lighthouse effectué à la première étape a été suggéré dans la section Préconnexion aux origines requises. Vous pouvez gagner environ 400 ms en établissant des connexions anticipées avec les sites statiquesxx.facebook.com et youtube.com:

Connectez-vous à l&#39;avance à l&#39;audit des origines requis en mettant en surbrillance le domaine &quot;staticxx.facebook.com&quot;.

Étant donné que le chargement de la vidéo YouTube est désormais différé, seule l'URL statiquexx.facebook.com est conservée. Il s'agit de la source du widget de partage sur les réseaux sociaux. Pour établir une connexion anticipée, il vous suffit d'ajouter une balise <link> au <head> du document:

  <link rel="preconnect" href="https://staticxx.facebook.com">

Réévaluer les performances

Voici l'état de la page après l'optimisation. Suivez les étapes de la section Mesurer les performances de l'atelier de programmation pour exécuter un autre audit Lighthouse.

Audit Lighthouse indiquant un FCP d&#39;une seconde et un score de performances de 99.