Les scripts tiers ont un impact sur les performances. Il est donc important de les auditer régulièrement et d'utiliser des techniques de chargement efficaces. Cet atelier de programmation vous explique comment optimiser le chargement des ressources tierces. Il aborde les techniques suivantes:
Reporter le chargement du script
Ressources non critiques à chargement différé
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 de données permettant d'afficher un graphique linéaire
Un widget de partage sur les réseaux sociaux
Vous commencerez par mesurer les performances de l'application, puis vous appliquerez chaque technique pour améliorer différents aspects des performances de l'application.
Évaluer les performances
Commencez par ouvrir l'application exemple en plein écran:
- Cliquez sur Remix to Edit (Remixer pour modifier) pour pouvoir modifier le projet.
- Pour prévisualiser le site, appuyez sur Afficher l'application. Appuyez ensuite sur Plein écran
Effectuez un audit de performances Lighthouse sur la page pour établir des performances de référence:
- Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
- Cliquez sur l'onglet Lighthouse.
- Cliquez sur Mobile.
- Cochez la case Performances. (Vous pouvez décocher les autres cases dans la section "Audits".)
- Cliquez sur Simulée de 3G rapide, Ralentissement du processeur 4x.
- Cochez la case Vider l'espace de stockage.
- Cliquez sur Exécuter des audits.
Lorsque vous effectuez un audit sur votre machine, les résultats exacts peuvent varier, mais vous devez noter que la durée First Contentful Paint (FCP) est assez élevée et que Lighthouse suggère deux pistes à explorer: Éliminer les ressources bloquant l'affichage et Se préconnecter aux origines requises. (Même si toutes les métriques sont affichées en vert, les optimisations permettront quand même d'obtenir des améliorations.)
Reporter le code JavaScript tiers
L'audit Éliminer les ressources bloquant l'affichage indique 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 les fonctions utilitaires D3 pour créer le graphique en courbes SVG et l'ajouter à la page. L'ordre des opérations ici est important: 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 de fermeture </body>
dans index.html
.
Cependant, le script D3 est inclus dans le fichier <head>
de la page, ce qui bloque l'analyse du reste du document:
Deux attributs magiques peuvent débloquer l'analyseur lorsqu'il est ajouté à la balise de script:
async
garantit que les scripts se téléchargent en arrière-plan et s'exécutent à la première occasion après la fin du téléchargement.defer
garantit que les scripts se téléchargent 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 se trouvera probablement en dessous de la ligne de flottaison, utilisez defer
pour vous assurer qu'il n'y a pas de blocage de l'analyseur.
É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 génère une erreur.
Les scripts dotés de l'attribut defer
s'exécutent dans l'ordre dans lequel ils ont été spécifiés. Pour vous assurer que script.js
s'exécute 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>
de D3. Désormais, il ne bloque plus l'analyseur, et le téléchargement démarre plus tôt.
<script src="https://d3js.org/d3.v3.min.js" defer></script>
<script src="./script.js" defer></script>
Ressources tierces à chargement différé
Toutes les ressources situées en dessous de la ligne de flottaison sont de bonnes candidates au chargement différé.
L'application exemple intègre une vidéo YouTube dans un iFrame. Pour connaître le nombre de demandes générées par la page et celles provenant de l'iFrame YouTube intégré:
- Pour prévisualiser le site, appuyez sur Afficher l'application. Appuyez ensuite sur Plein écran
- Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
- 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é 28 requêtes au total 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 Initiator (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 requêtes par domaine, cliquez sur le titre de la colonne Domains (Domaines).
Le nouveau tri indique la présence de requêtes supplémentaires auprès des domaines Google. Au total, l'iFrame YouTube génère 14 demandes de scripts, de feuilles de style, d'images et de polices. Mais à 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 qu'un utilisateur fasse défiler la page jusqu'à cette section, vous réduisez le nombre de demandes initiales de la page. Cette approche évite aux utilisateurs et accélère le chargement initial.
Pour implémenter le chargement différé, vous pouvez utiliser Intersection Observer, une API de navigateur qui vous avertit lorsqu'un élément arrive dans la fenêtre d'affichage du navigateur ou en sort.
Étape 1: Empêchez le chargement initial de la vidéo
Pour effectuer un chargement différé de l'iFrame vidéo, vous devez d'abord empêcher son chargement comme d'habitude. 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 des éléments HTML standards. Vous pouvez nommer un attribut de données comme vous le souhaitez, à condition qu'il commence par "data-".
Un iFrame sans src
ne se charge tout simplement pas.
Étape 2: Utilisez Intersection Observer pour charger la vidéo en différé
Pour charger la vidéo lorsqu'un utilisateur la fait défiler, vous devez savoir à quel moment 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 Nouveau fichier et donnez-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 à 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 d'entrée dans la fenêtre d'affichage, etc. L'une des propriétés de IntersectionObserverEntry
est isIntersecting
, 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 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. Appuyez ensuite sur Plein écran
- Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
- Cliquez sur l'onglet Console.
Essayez de faire défiler l'écran vers le haut et vers le bas. La valeur de isIntersecting
doit changer et l'élément cible doit ê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 la 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éévaluer 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 de nouveau la page. Le panneau Network (Réseau) indique que la page a effectué 14 requêtes et que sa taille est limitée à 260 Ko. C'est une amélioration significative !
Maintenant, faites défiler la page vers le bas et gardez un œil sur le panneau Network (Réseau). Lorsque vous arrivez à la vidéo, la page doit déclencher des requêtes supplémentaires.
Se préconnecter aux origines requises
Vous avez différé le code JavaScript non critique et le chargement différé des requêtes YouTube. Il est donc temps 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 requête pour cette ressource ne soit effectuée. Il est préférable d'utiliser cet attribut sur les origines qui fournissent les ressources dont vous êtes certain que la page a besoin.
L'audit Lighthouse que vous avez effectué à la première étape était suggéré dans Préconnexion aux origines requises. Vous pouvez gagner environ 400 ms en établissant les premières connexions à statiquexx.facebook.com et youtube.com:
Étant donné que la vidéo YouTube est à présent chargée en différé, seul le site statiquexx.facebook.com est la source du widget de partage sur les réseaux sociaux. Pour établir une connexion anticipée à ce domaine, il suffit d'ajouter une balise <link>
au fichier <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 exécuter un autre audit Lighthouse.