Les scripts tiers ont un impact sur les performances. C'est pourquoi il est important de les examiner régulièrement et d'utiliser des techniques de chargement efficaces. Cet atelier de programmation vous explique comment optimiser le chargement de ressources tierces. Il aborde les techniques suivantes:
Différer le chargement du script
Chargement différé des ressources non critiques
Préconnexion aux origines requises
L'application exemple incluse comporte une page Web simple avec trois fonctionnalités provenant de sources tierces:
Intégration d'une vidéo
Bibliothèque de visualisation des données pour afficher un graphique en courbes
Un widget de partage sur les réseaux sociaux
Vous commencerez par mesurer les performances de l'application, puis appliquerez chaque technique pour améliorer différents aspects de ses performances.
Évaluer les performances
Ouvrez d'abord l'application exemple en plein écran:
- Cliquez sur Remixer pour modifier pour rendre le projet modifiable.
- Pour prévisualiser le site, appuyez sur Afficher l'application, puis sur Plein écran .
Effectuez un audit de performances Lighthouse sur la page pour établir les performances de référence:
- Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir DevTools.
- Cliquez sur l'onglet Lighthouse (Phare).
- Cliquez sur Mobile.
- Cochez la case Performances. (Vous pouvez décocher les autres cases de la section "Audits".)
- Cliquez sur Connexion 3G rapide simulée, processeur 4 fois plus lent.
- Cochez la case Effacer l'espace de stockage.
- Cliquez sur Effectuer des audits.
Lorsque vous exécutez un audit sur votre machine, les résultats exacts peuvent varier, mais vous devriez remarquer que le temps de First Contentful Paint (FCP) est assez élevé et que Lighthouse suggère deux possibilités d'investigation: Éliminer les ressources bloquant le rendu et Preconnecter aux origines requises. (Même si toutes les métriques sont vertes, les optimisations apporteront des améliorations.)
Différer le code JavaScript tiers
L'audit Éliminer les ressources bloquant l'affichage a révélé que vous pouvez gagner du temps en différant un script provenant de d3js.org:
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 il est inclus juste avant la balise </body>
de fermeture dans index.html
.
Toutefois, le script D3 est inclus dans le <head>
de la page, ce qui bloque l'analyse du reste du document:
Deux attributs magiques peuvent débloquer l'analyseur lorsqu'ils sont ajoutés à la balise de script:
async
garantit que les scripts sont téléchargés en arrière-plan et exécutés à 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 exécutés après l'analyse.
Étant donné que ce graphique n'est pas vraiment essentiel à la page globale et qu'il se trouvera probablement en dessous de la ligne de flottaison, utilisez defer
pour vous assurer qu'aucun blocage de l'analyseur n'est effectué.
Étape 1: Chargez le script de manière asynchrone avec l'attribut defer
Sur 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érifier l'ordre correct des opérations
Maintenant que D3 est différé, script.js
s'exécute avant que D3 ne soit prêt, ce qui entraîne 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é après que D3 est prêt, ajoutez-y defer
et déplacez-le vers le haut, dans la section <head>
du document, juste après l'élément <script>
D3. 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>
Charger de façon différée des ressources tierces
Toutes les ressources situées en dessous de la ligne de flottaison sont de bons candidats pour le chargement différé.
L'application exemple comporte une vidéo YouTube intégrée dans un iFrame. Pour vérifier le nombre de requêtes effectuées par la page et celles qui proviennent de l'iFrame YouTube intégrée:
- Pour prévisualiser le site, appuyez sur Afficher l'application, puis sur Plein écran .
- Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir DevTools.
- Cliquez sur l'onglet Réseau.
- Cochez la case Disable cache (Désactiver le cache).
- Sélectionnez 3G rapide dans le menu déroulant Limitation.
- Actualisez la page.
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 requêtes envoyées par le iframe
YouTube, recherchez l'ID de la vidéo 6lfaiXM6waw
dans la colonne Initiateur. Pour regrouper toutes les demandes par domaine:
Dans le panneau Réseau, effectuez un clic droit sur un titre de colonne.
Dans le menu déroulant, sélectionnez la colonne Domains (Domaines).
Pour trier les requêtes par domaine, cliquez sur l'en-tête de la colonne Domains (Domaines).
Le nouveau tri révèle qu'il existe des requêtes supplémentaires adressées aux domaines Google. Au total, l'iFrame YouTube effectue 14 requêtes pour les scripts, les feuilles de style, les images et les polices. Toutefois, à moins que les utilisateurs ne fassent défiler l'écran pour lire la vidéo, ils n'ont pas vraiment besoin de tous ces éléments.
En attendant de charger la vidéo de manière différée jusqu'à ce qu'un utilisateur fasse défiler la page jusqu'à cette section, vous réduisez le nombre de requêtes envoyées par la page au départ. Cette approche permet d'économiser les données des utilisateurs et d'accélérer la charge initiale.
Une façon d'implémenter le chargement différé consiste à utiliser Intersection Observer, une API de navigateur qui vous avertit lorsqu'un élément entre ou sort de la fenêtre d'affichage du navigateur.
Étape 1: Empêcher le chargement initial de la vidéo
Pour charger de manière différée l'iframe vidéo, vous devez d'abord l'empêcher de se charger de la manière habituelle. Pour ce faire, remplacez l'attribut src
par l'attribut data-src
afin de spécifier 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 donner n'importe quel nom à un attribut de données, à condition qu'il commence par "data-".
Un iframe sans src
ne se charge tout simplement pas.
Étape 2: Utiliser Intersection Observer pour charger la vidéo de manière différée
Pour charger la vidéo lorsqu'un utilisateur y fait défiler la page, 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 est exécutée chaque fois qu'un élément que vous souhaitez suivre entre ou sort du viewport.
Pour commencer, créez un fichier et nommez-le lazy-load.js
:
- Cliquez sur Nouveau fichier et donnez-lui un nom.
- Cliquez sur Ajouter ce fichier.
Ajoutez la balise 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);
Indiquez maintenant à observer
un élément cible à regarder (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 le viewport, etc. L'une des propriétés de IntersectionObserverEntry
est isIntersecting
, une valeur booléenne qui est é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 voir comment cela fonctionne, 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);
});
});
- Pour prévisualiser le site, appuyez sur Afficher l'application, puis sur Plein écran .
- Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir DevTools.
- Cliquez sur l'onglet Console.
Essayez de faire défiler l'écran vers le haut et vers le bas. La valeur de isIntersecting
devrait changer, et l'élément cible devrait être 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 surveiller 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éévaluer les performances
Pour voir comment la taille et le nombre de ressources ont changé, ouvrez le panneau Network (Réseau) des outils pour les développeurs, puis actualisez à nouveau la page. Le panneau Network (Réseau) indique que la page a effectué 14 requêtes et seulement 260 ko. C'est une amélioration significative !
Faites défiler la page vers le bas et observez le panneau Network (Réseau). Lorsque vous accédez à la vidéo, la page devrait déclencher des requêtes supplémentaires.
Connectez-vous à l'avance aux origines requises
Vous avez différé le code JavaScript non critique et chargé les requêtes YouTube de manière lazy-loading. Il est maintenant temps d'optimiser le reste du contenu tiers.
Ajouter l'attribut rel=preconnect
à un lien indique au navigateur d'établir une connexion à un domaine avant d'effectuer la requête pour cette ressource. Cet attribut est particulièrement utile pour les origines qui fournissent des ressources dont vous êtes certain que la page a besoin.
L'audit Lighthouse que vous avez effectué à la première étape, dans la section Preconnect to required origins (Préconnecter aux origines requises), vous a suggéré que vous pouviez économiser environ 400 ms en établissant des connexions anticipées à staticxx.facebook.com et youtube.com:
Étant donné que la vidéo YouTube est désormais chargée de manière différée, il ne reste que staticxx.facebook.com, la source du widget de partage sur les réseaux sociaux. Pour établir une connexion anticipée à ce domaine, il vous suffit d'ajouter une balise <link>
à l'<head>
du document:
<link rel="preconnect" href="https://staticxx.facebook.com">
Réévaluer les performances
Voici l'état de la page après optimisation. Suivez les étapes de la section Mesurer les performances de l'atelier de programmation pour effectuer un autre audit Lighthouse.