Les performances Web en toute simplicité – Google I/O, édition 2018

Lors de la conférence Google IO 2018, nous avons présenté un récapitulatif d'outils, de bibliothèques et de techniques d'optimisation permettant d'améliorer plus facilement les performances Web. Nous les expliquons ici à l'aide de l'application Oodles Theater. Nous parlons également de nos tests du chargement prédictif et de la nouvelle initiative Guess.js.

Addy Osmani
Addy Osmani
Ewa Gasperowicz

Au cours de l'année écoulée, nous avons été très occupés à essayer de rendre le Web plus rapide et plus performant. Nous avons donc développé de nouveaux outils, approches et bibliothèques que nous souhaitons vous présenter dans cet article. Dans la première partie, nous vous présenterons quelques techniques d'optimisation que nous avons utilisées en pratique pour développer l'application Oodles Theater. Dans la seconde partie, nous évoquerons nos tests avec le chargement prédictif et la nouvelle initiative Guess.js.

Le besoin de performances

Internet devient de plus en plus lourd d'année en année. Si nous vérifions l'état du Web, nous constatons qu'une page médiane sur mobile pèse environ 1,5 Mo, la majorité étant composée de code JavaScript et d'images.

La taille croissante des sites Web, ainsi que d'autres facteurs, tels que la latence du réseau, les limites du processeur, les modèles de blocage du rendu ou le code tiers superflu, contribuent à la complexité de l'équation des performances.

La plupart des utilisateurs évaluent la vitesse comme étant au tout haut de la hiérarchie UX de leurs besoins. Ce n'est pas trop surprenant, car vous ne pouvez pas faire grand-chose tant que le chargement d'une page n'est pas terminé. Vous ne pouvez pas en tirer de valeur, ni admirer son esthétique.

Pyramide de la hiérarchie de l'expérience utilisateur
Fig. 1. Dans quelle mesure la vitesse est-elle importante pour les utilisateurs ? (Speed Matters, Vol. 3)

Nous savons que les performances sont importantes pour les utilisateurs, mais cela peut aussi sembler secret pour savoir par où commencer pour optimiser les performances. Heureusement, il existe des outils qui peuvent vous aider.

Lighthouse : base du workflow de performances

Lighthouse fait partie des outils pour les développeurs Chrome et vous permet de réaliser un audit de votre site Web et de vous donner des conseils pour l'améliorer.

Nous avons récemment lancé de nombreux audits de performances qui sont très utiles dans le workflow de développement quotidien.

Nouveaux audits Lighthouse
Fig. 2. Nouveaux audits Lighthouse

Voyons comment en tirer parti avec un exemple concret : l'application Oodles Theater. Il s'agit d'une petite application Web de démonstration dans laquelle vous pouvez essayer certains de nos Doodles Google interactifs préférés et même jouer à un ou deux jeux.

Lors de la création de l'application, nous voulions nous assurer qu'elle était aussi performante que possible. L'optimisation a été basée sur un rapport Lighthouse.

Rapport Lighthouse pour l'application Oodles
Fig. 3. Rapport Lighthouse pour l'application Oodles

Les performances initiales de notre application telles qu'elles ont été observées dans le rapport Lighthouse étaient plutôt mauvaises. Sur un réseau 3G, l'utilisateur devait attendre 15 secondes pour la première peinture significative ou pour que l'application devienne interactive. Lighthouse a mis en évidence de nombreux problèmes sur notre site, et le score de performances global de 23 reflète exactement cela.

La page pesait environ 3,4 Mo. Nous devions absolument réduire son poids.

C'est ainsi que nous avons commencé notre premier défi de performances : trouver des éléments que nous pouvons facilement supprimer sans affecter l'expérience globale.

Opportunités d'optimisation des performances

Supprimer les ressources inutiles

Certains éléments évidents peuvent être supprimés en toute sécurité : les espaces et les commentaires.

Gains générés par la minimisation
Fig. 4. Réduire la taille des ressources JavaScript et CSS et les compresser

Lighthouse met en avant cette opportunité dans l'audit CSS et JavaScript non minifiés. Comme nous utilisions webpack pour notre processus de compilation, nous avons simplement utilisé le plug-in Uglify JS afin d'obtenir la minimisation.

La minimisation est une tâche courante. Vous devez donc être en mesure de trouver une solution prête à l'emploi pour le processus de compilation que vous utilisez.

Un autre audit utile dans ce domaine est Activer la compression de texte. Il n'y a aucune raison d'envoyer des fichiers non compressés, et la plupart des CDN le prennent en charge dès la sortie de la boîte.

Nous utilisions Firebase Hosting pour héberger notre code, et Firebase active le compression gzip par défaut. Par conséquent, nous avons obtenu cela sans frais en hébergeant notre code sur un CDN raisonnable.

Bien que gzip soit un moyen de compression très populaire, d'autres mécanismes tels que Zopfli et Brotli sont également utilisés. Brotli est compatible avec la plupart des navigateurs. Vous pouvez utiliser un binaire pour précompresser vos composants avant de les envoyer au serveur.

Utiliser des règles de cache efficaces

Nous avons ensuite veillé à ne pas envoyer de ressources deux fois si ce n'était pas nécessaire.

L'audit Politique de cache inefficace dans Lighthouse nous a permis de constater que nous pouvions optimiser nos stratégies de mise en cache pour y parvenir. En définissant un en-tête d'expiration max-age sur notre serveur, nous nous sommes assurés qu'en cas de nouvelle visite, l'utilisateur peut réutiliser les ressources qu'il a téléchargées précédemment.

Idéalement, vous devriez chercher à mettre en cache autant de ressources que possible de manière sécurisée pendant la période la plus longue possible et fournir des jetons de validation pour revalider efficacement les ressources mises à jour.

Supprimer le code inutilisé

Jusqu'à présent, nous avons supprimé les parties évidentes du téléchargement inutile, mais qu'en est-il des parties moins évidentes ? Par exemple, du code inutilisé.

Couverture de code dans les outils de développement
Fig. 5. Vérifier la couverture du code

Il arrive que nous incluions dans nos applications du code qui n'est pas vraiment nécessaire. Cela se produit en particulier si vous travaillez sur votre application pendant une longue période, que votre équipe ou vos dépendances changent, et qu'une bibliothèque orpheline est parfois laissée de côté. C'est exactement ce qui nous est arrivé.

Au début, nous utilisions la bibliothèque Material Components pour créer rapidement un prototype de notre application. Au fil du temps, nous sommes passés à un style plus personnalisé et nous avons complètement oublié cette bibliothèque. Heureusement, la vérification de la couverture du code nous a permis de le redécouvrir dans notre bundle.

Vous pouvez consulter les statistiques de couverture de code dans DevTools, à la fois pour l'environnement d'exécution et pour le temps de chargement de votre application. Vous pouvez voir les deux grandes bandes rouges dans la capture d'écran du bas. Plus de 95 % de notre CSS était inutilisé, ainsi qu'une grande quantité de JavaScript.

Lighthouse a également détecté ce problème lors de l'audit des règles CSS inutilisées. Il a permis d'économiser plus de 400 ko. Nous sommes donc revenus à notre code et avons supprimé la partie JavaScript et CSS de cette bibliothèque.

Si nous supprimons l'adaptateur MVC, nos styles passent à 10 ko.
Fig. 6. Si nous abandonnons l'adaptateur MVC, nos styles passent à 10 ko.

Cela a réduit notre bundle CSS de 20 fois, ce qui est plutôt bien pour un commit minuscule de deux lignes.

Bien entendu, cela a fait grimper notre score de performances, et le temps de réponse à l'interaction s'est également beaucoup amélioré.

Toutefois, avec des changements comme celui-ci, il ne suffit pas de vérifier vos métriques et vos scores. La suppression de code n'est jamais sans risque. Vous devez donc toujours rechercher des régressions potentielles.

Notre code n'était pas utilisé dans 95 % des cas, mais il reste encore 5 %. Apparemment, l'un de nos composants utilisait toujours les styles de cette bibliothèque (les petites flèches dans le curseur de dessin). Comme il était très petit, nous pouvions simplement réintégrer manuellement ces styles dans les boutons.

Les boutons ont été endommagés par une bibliothèque manquante
Fig. 7. Un composant utilisait toujours la bibliothèque supprimée.

Par conséquent, si vous supprimez du code, assurez-vous simplement de disposer d'un workflow de test approprié pour vous protéger contre les régressions visuelles potentielles.

Évitez d'énormes charges utiles de réseau

Nous savons que les ressources volumineuses peuvent ralentir le chargement des pages Web. Elles peuvent coûter de l'argent à nos utilisateurs et avoir un impact important sur leurs forfaits de données. Il est donc très important d'en tenir compte.

Lighthouse a détecté un problème avec certaines de nos charges utiles réseau à l'aide de l'audit Charge utile réseau énorme.

Détecter d'énormes charges utiles de réseau
Fig. 8. Détecter d'énormes charges utiles réseau

Nous avons constaté que plus de 3 Mo de code étaient envoyés, ce qui est assez important, en particulier sur mobile.

En haut de cette liste, Lighthouse a indiqué que nous avions un bundle de fournisseurs JavaScript de 2 Mo de code non compressé. C'est également un problème mis en évidence par webpack.

Comme dit le proverbe, la requête la plus rapide est celle qui n'est pas envoyée.

Idéalement, vous devez mesurer la valeur de chaque élément que vous diffusez auprès de vos utilisateurs, mesurer les performances de ces éléments et déterminer s'il est vraiment utile de les diffuser avec l'expérience initiale. Parce que ces éléments peuvent parfois être différés, chargés en différé ou traités pendant la période d'inactivité.

Dans notre cas, comme nous traitons de nombreux bundles JavaScript, nous avons eu de la chance, car la communauté JavaScript dispose d'un ensemble complet d'outils d'audit des bundles JavaScript.

Audit des bundles JavaScript
Figure 9. Audit du bundle JavaScript

Nous avons commencé par utiliser l'analyseur de bundle webpack, qui nous a informés que nous incluions une dépendance appelée unicode, qui représentait 1,6 Mo de code JavaScript analysé.

Nous sommes ensuite passés à notre éditeur et, à l'aide du plug-in de coût d'importation pour le code visuel, nous avons pu visualiser le coût de chaque module que nous importions. Cela nous a permis de découvrir quel composant comprenait du code qui faisait référence à ce module.

Nous avons ensuite passé à un autre outil, BundlePhobia. Il s'agit d'un outil qui vous permet de saisir le nom de n'importe quel package NPM et de voir quelle est sa taille estimée en minifié et en gzippé. Nous avons trouvé une bonne alternative au module slug que nous utilisions, qui ne pèse que 2,2 ko. Nous l'avons donc remplacé.

Cela a eu un impact important sur nos performances. Entre ce changement et la découverte d'autres possibilités de réduire la taille de notre bundle JavaScript, nous avons économisé 2,1 Mo de code.

Nous avons constaté une amélioration de 65 % dans l'ensemble, en tenant compte de la taille compressée et minifiée de ces bundles. Nous avons constaté que ce processus était vraiment utile.

En règle générale, essayez d'éliminer les téléchargements inutiles sur vos sites et dans vos applications. Faire l'inventaire de vos composants et mesurer leur impact sur les performances peut avoir un impact très important. Veillez donc à auditer vos composants assez régulièrement.

Diminution du temps de démarrage de JavaScript grâce à la division du code

Bien que les charges utiles réseau volumineuses puissent avoir un impact important sur notre application, un autre élément qui peut avoir un impact très important est JavaScript.

JavaScript est votre élément le plus cher. Sur mobile, si vous envoyez des lots volumineux de JavaScript, le délai d'interaction des utilisateurs avec les composants de l'interface utilisateur peut être retardé. Cela signifie qu'ils peuvent appuyer sur l'interface utilisateur sans que rien de significatif ne se produise. Il est donc important de comprendre pourquoi JavaScript coûte si cher.

C'est ainsi qu'un navigateur traite JavaScript.

Traitement JavaScript
Fig. 10. Traitement JavaScript

Nous devons d'abord télécharger ce script. Nous disposons d'un moteur JavaScript qui doit ensuite analyser ce code, le compiler et l'exécuter.

Ces phases ne prennent pas beaucoup de temps sur un appareil haut de gamme comme un ordinateur de bureau ou un ordinateur portable, voire un téléphone haut de gamme. Toutefois, sur un téléphone mobile moyen, ce processus peut prendre entre cinq et dix fois plus de temps. C'est ce qui retarde l'interactivité. Il est donc important que nous essayions de réduire ce délai.

Pour vous aider à identifier ces problèmes dans votre application, nous avons ajouté un nouvel audit du temps de démarrage JavaScript à Lighthouse.

Délai de démarrage de JavaScript
Fig. 11 Audit du temps de démarrage de JavaScript

Et dans le cas de l'application Oodle, cela nous a indiqué que nous avions passé 1,8 seconde à effectuer le démarrage de JavaScript. Nous importions de manière statique tous nos routes et composants dans un seul bundle JavaScript monolithique.

Pour contourner ce problème, vous pouvez utiliser la division du code.

La division du code est comme une pizza

Le fractionnement du code consiste à ne pas fournir à vos utilisateurs une pizza entière de code JavaScript, mais une seule part à la fois, selon leurs besoins.

La division du code peut être appliquée au niveau d'un itinéraire ou d'un composant. Il fonctionne parfaitement avec React et React Loadable, Vue.js, Angular, Polymer, Preact et plusieurs autres bibliothèques.

Nous avons intégré la division du code dans notre application, et sommes passés des importations statiques aux importations dynamiques, ce qui nous a permis de charger du code de manière différée de manière asynchrone en fonction de nos besoins.

Fractionnement du code avec des importations dynamiques
Fig. 13 : Fractionnement du code avec des importations dynamiques

Cela a eu pour effet de réduire la taille de nos bundles, mais aussi le temps de démarrage JavaScript. Le temps d'exécution est ainsi passé à 0,78 seconde, ce qui a rendu l'application 56 % plus rapide.

En général, si vous créez une expérience qui utilise beaucoup JavaScript, veillez à n'envoyer le code qu'à l'utilisateur dont il a besoin.

Profitez de concepts tels que le fractionnement du code, explorez des idées comme le ramassage d'arbres et consultez le dépôt webpack-libs-optimizations pour obtenir quelques idées sur la façon de réduire la taille de votre bibliothèque si vous utilisez webpack.

Optimiser les images

Blague sur les performances de chargement des images

Dans l'application Oodle, nous utilisons beaucoup d'images. Malheureusement, Lighthouse a été beaucoup moins enthousiaste que nous. En fait, nous avons échoué aux trois audits liés aux images.

Nous avons oublié d'optimiser nos images, nous ne les avons pas dimensionnées correctement et nous pourrions gagner à utiliser d'autres formats d'images.

Audits des images
Fig. 14 Audits d'images Lighthouse

Nous avons commencé par optimiser nos images.

Pour une phase d'optimisation ponctuelle, vous pouvez utiliser des outils visuels tels que ImageOptim ou XNConvert.

Une approche plus automatisée consiste à ajouter une étape d'optimisation d'image à votre processus de compilation, à l'aide de bibliothèques telles que imagemin.

Ainsi, vous vous assurez que les images ajoutées par la suite seront optimisées automatiquement. Certains CDN (comme Akamai) ou des solutions tierces telles que Cloudinary, Fastly ou Uploadcare vous offrent des solutions complètes d'optimisation des images. Vous pouvez ainsi simplement héberger vos images sur ces services.

Si vous ne souhaitez pas le faire en raison des coûts ou des problèmes de latence, des projets tels que Thumbor ou Imageflow proposent des alternatives auto-hébergées.

Avant et après l'optimisation
Figure 15 Avant et après optimisation

Notre image PNG d'arrière-plan a été signalée dans Webpack comme étant grande, et ce à juste titre. Après l'avoir correctement dimensionnée par rapport à la fenêtre d'affichage et exécutée via ImageOptim, nous sommes descendus à 100 Ko, ce qui est acceptable.

En répétant cette opération pour plusieurs images de notre site, nous avons pu réduire considérablement le poids global de la page.

Utiliser le format adapté pour le contenu animé

Les GIF peuvent être très coûteux. Étonnamment, le format GIF n'a jamais été conçu comme une plate-forme d'animation. Par conséquent, passer à un format vidéo plus adapté vous permet de réaliser d'importantes économies en termes de taille de fichier.

Dans l'application Oodle, nous utilisions un GIF comme séquence d'introduction sur la page d'accueil. Selon Lighthouse, nous pourrions économiser plus de 7 Mo en passant à un format vidéo plus efficace. Notre extrait pesait environ 7,3 Mo, bien trop pour un site Web raisonnable. Nous l'avons donc transformé en élément vidéo avec deux fichiers sources : un MP4 et un WebM pour une compatibilité plus large avec les navigateurs.

Remplacer les GIF animés par des vidéos
Figure 16 Remplacer les GIF animés par des vidéos

Nous avons utilisé l'outil FFmpeg pour convertir notre GIF d'animation au format mp4. Le format WebM vous permet de réaliser des économies encore plus importantes. L'API ImageOptim peut effectuer cette conversion pour vous.

ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4

Nous avons réussi à économiser plus de 80 % de notre poids total grâce à cette conversion. Nous sommes ainsi passés à environ 1 Mo.

Toutefois, 1 Mo est une ressource importante à transmettre par câble, en particulier pour un utilisateur dont la bande passante est limitée. Heureusement, nous pouvons utiliser l'API Effective Type pour nous rendre compte qu'ils utilisent une bande passante lente et leur fournir un fichier JPEG beaucoup plus petit à la place.

Cette interface utilise la valeur effective du temps aller-retour et de la mise hors service pour estimer le type de réseau utilisé par l'utilisateur. Il renvoie simplement une chaîne, 2G lente, 2G, 3G ou 4G. En fonction de cette valeur, si l'utilisateur dispose d'une connexion inférieure à la 4G, nous pouvons remplacer l'élément vidéo par l'image.

if (navigator.connection.effectiveType) { ... }

Cela réduit un peu l'expérience, mais au moins le site est utilisable avec une connexion lente.

Chargement différé des images hors écran

Les carrousels, les curseurs ou les pages très longues chargent souvent des images, même si l'utilisateur ne peut pas les voir immédiatement sur la page.

Lighthouse signale ce comportement lors de l'audit des images hors écran. Vous pouvez également le constater par vous-même dans le panneau "Network" (Réseau) des outils de développement. Si de nombreuses images sont entrantes alors que seules quelques-unes sont visibles sur la page, vous pouvez peut-être envisager de les charger en différé.

Le chargement paresseux n'est pas encore pris en charge en mode natif dans le navigateur. Nous devons donc utiliser JavaScript pour ajouter cette fonctionnalité. Nous avons utilisé la bibliothèque Lazysizes pour ajouter un comportement de chargement paresseux à nos couvertures Oodle.

<!-- Import library -->
import lazysizes from 'lazysizes'  <!-- or -->
<script src="lazysizes.min.js"></script>

<!-- Use it -->

<img data-src="image.jpg" class="lazyload"/>
<img class="lazyload"
    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w"/>

Lazysizes est intelligent, car il ne suit pas seulement les modifications de visibilité de l'élément, mais précharge également de manière proactive les éléments proches de la vue pour une expérience utilisateur optimale. Il propose également une intégration facultative de IntersectionObserver, qui vous permet d'effectuer des recherches de visibilité très efficaces.

Depuis cette modification, nos images sont récupérées à la demande. Si vous souhaitez approfondir ce sujet, consultez images.guide, une ressource très pratique et complète.

Aider le navigateur à fournir des ressources critiques plus tôt

Tous les octets envoyés au navigateur par le biais du fil n'ont pas le même degré d'importance, et le navigateur le sait. De nombreux navigateurs utilisent des méthodes heuristiques pour décider de ce qu'ils doivent extraire en premier. Il arrive donc qu'ils récupèrent le CSS avant les images ou les scripts.

Il peut être utile que nous, en tant qu'auteurs de la page, informions le navigateur de ce qui est vraiment important pour nous. Heureusement, au cours des deux dernières années, les fournisseurs de navigateurs ont ajouté un certain nombre de fonctionnalités pour nous aider, par exemple des indices de ressources tels que link rel=preconnect, preload ou prefetch.

Ces fonctionnalités apportées à la plate-forme Web aident le navigateur à récupérer le bon élément au bon moment. Elles peuvent être un peu plus efficaces que certaines des approches de chargement personnalisé basées sur la logique qui sont effectuées à l'aide de scripts.

Voyons comment Lighthouse nous aide à utiliser efficacement certaines de ces fonctionnalités.

La première chose que Lighthouse nous demande de faire est d'éviter les allers-retours multiples et coûteux vers n'importe quelle origine.

Éviter les multiples allers-retours coûteux vers n&#39;importe quelle origine
Figure 17 : Éviter les allers-retours multiples et coûteux vers n'importe quelle origine

Dans le cas de l'application Oodle, nous utilisons beaucoup Google Fonts. Chaque fois que vous insérez une feuille de style de police Google sur votre page, elle se connecte à deux sous-domaines. De plus, ce que nous dit Lighthouse, c'est que si nous pouvions préchauffer cette connexion, nous pourrions gagner jusqu'à 300 millisecondes lors de notre temps de connexion initiale.

En profitant de la préconnexion de lien rel, nous pouvons masquer efficacement cette latence de connexion.

Cela peut avoir un impact très important, en particulier avec Google Fonts, où notre CSS de polices de caractères est hébergé sur googleapis.com et nos ressources de polices sur Gstatic. Nous avons donc appliqué cette optimisation, ce qui nous a permis de gagner quelques centaines de millisecondes.

Lighthouse suggère ensuite de précharger les requêtes clés.

Précharger les requêtes de clé
Fig. 18 : Précharger les requêtes de clé

<link rel=preload> est très puissant. Il informe le navigateur qu'une ressource est nécessaire dans le cadre de la navigation en cours et tente de le récupérer dès que possible.

Ici, Lighthouse nous indique que nous devrions précharger nos principales ressources de polices Web, car nous chargeons deux polices Web.

Le préchargement dans une police Web ressemble à ceci : en spécifiant rel=preload, vous transmettez as avec le type de police, puis vous spécifiez le type de police que vous essayez de charger, par exemple woff2.

L'impact que cela peut avoir sur votre page est assez brutal.

Impact du préchargement des ressources
Fig. 19 Impact du préchargement des ressources

Normalement, sans utiliser le préchargement de lien rel, si les polices Web sont essentielles à votre page, le navigateur doit d'abord récupérer votre code HTML, analyser votre code CSS, puis récupérer vos polices Web.

Avec le préchargement de lien rel, dès que le navigateur a analysé votre code HTML, il peut commencer à extraire ces polices Web beaucoup plus tôt. Dans le cas de notre application, cela nous a permis de gagner une seconde sur le temps nécessaire pour afficher le texte à l'aide de nos polices Web.

Toutefois, si vous essayez de précharger des polices à l'aide de Google Fonts, il existe un piège.

Les URL de polices Google que nous spécifions pour nos polices dans nos feuilles de style sont mises à jour assez régulièrement par l'équipe chargée des polices. Ces URL peuvent expirer ou être mises à jour régulièrement. Nous vous suggérons donc d'héberger vous-même vos polices Web si vous souhaitez contrôler entièrement votre expérience de chargement de polices. Cela peut être très utile, car cela vous permet d'accéder à des éléments tels que le préchargement de liens rel.

Dans notre cas, l'outil Google Web Fonts Helper nous a été très utile pour nous aider à mettre hors connexion certaines de ces polices Web et à les configurer localement. N'hésitez donc pas à l'essayer.

Que vous utilisiez des polices Web dans vos ressources essentielles ou que ce soit JavaScript, essayez d'aider le navigateur à diffuser vos ressources essentielles le plus rapidement possible.

Expérimental: indications de priorité

Nous avons quelque chose de spécial à vous annoncer aujourd'hui. En plus de fonctionnalités telles que les optimisations de ressources et le préchargement, nous avons travaillé sur une toute nouvelle fonctionnalité expérimentale de navigateur que nous appelons "hints de priorité".

Définir la priorité du contenu initialement visible
Fig. 20 Indices de priorité

Il s'agit d'une nouvelle fonctionnalité qui vous permet d'indiquer au navigateur l'importance d'une ressource. Elle expose un nouvel attribut, l'importance, dont les valeurs sont faibles, élevées ou automatiques.

Cela nous permet de réduire la priorité des ressources moins importantes, telles que les styles, les images ou les appels d'API de récupération non critiques, afin de réduire les conflits. Nous pouvons également augmenter la priorité des éléments plus importants, comme nos images de héros.

Dans le cas de notre application Oodle, nous avons trouvé un emplacement pratique à optimiser.

Définir la priorité du contenu initialement visible
Fig. 21 Définissez la priorité du contenu initialement visible.

Avant d'ajouter le chargement paresseux à nos images, le navigateur avait un carrousel d'images avec tous nos gribouillages. Il récupérait toutes les images au tout début du carrousel avec une priorité élevée. Malheureusement, ce sont les images au milieu du carrousel qui étaient les plus importantes pour l'utilisateur. Nous avons donc défini l'importance de ces images de fond sur très faible, et celle des images de premier plan sur très élevée. Cela a eu un impact de deux secondes sur la 3G lente, et sur la rapidité avec laquelle nous avons pu extraire et afficher ces images. C'est donc une expérience positive.

Nous espérons déployer cette fonctionnalité dans Canary dans quelques semaines. Tenez-vous prêt.

Mettre en place une stratégie de chargement de polices Web

La typographie est essentielle à une bonne conception. Si vous utilisez des polices Web, vous ne devez pas bloquer le rendu de votre texte et vous ne devez pas afficher de texte invisible.

Nous le soulignons désormais dans Lighthouse avec l'audit Éviter le texte invisible pendant le chargement des polices Web.

Éviter le texte invisible pendant le chargement des polices Web
Fig. 22 : Éviter le texte invisible pendant le chargement des polices Web

Si vous chargez vos polices Web à l'aide d'un bloc de polices, le navigateur décide de la marche à suivre si l'extraction de cette police Web prend beaucoup de temps. Certains navigateurs attendent jusqu'à trois secondes avant de revenir à une police système. Ils finissent par la remplacer par cette police une fois le téléchargement terminé.

Nous essayons d'éviter ce texte invisible. Dans notre cas, nous n'aurions pas pu voir les doodles classiques de la semaine si la police Web avait pris trop de temps. Heureusement, une nouvelle fonctionnalité appelée font-display vous offre beaucoup plus de contrôle sur ce processus.

    @font-face {
      font-family: 'Montserrat';
      font-style: normal;
      font-display: swap;
      font-weight: 400;
      src: local('Montserrat Regular'), local('Montserrat-Regular'),
          /* Chrome 26+, Opera 23+, Firefox 39+ */
          url('montserrat-v12-latin-regular.woff2') format('woff2'),
            /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
          url('montserrat-v12-latin-regular.woff') format('woff');
    }

L'affichage des polices vous aide à déterminer comment les polices Web seront affichées ou remplacées en fonction du temps nécessaire pour les échanger.

Dans ce cas, nous utilisons l'échange d'affichage de la police. Avec Swap, la police a une période de bloc de 0 seconde et une période d'échange infinie. Cela signifie que le navigateur va dessiner votre texte assez rapidement avec une police de remplacement si le chargement de la police prend un certain temps. Il va le remplacer une fois que la police sera disponible.

Dans le cas de notre application, cela nous a permis d'afficher du texte pertinent très tôt et de passer à la police Web une fois qu'elle était prête.

Résultat de l&#39;affichage de la police
Fig. 23 : Résultat de l'affichage de la police

En règle générale, si vous utilisez des polices Web, comme le fait une grande partie du Web, mettez en place une bonne stratégie de chargement de polices Web.

De nombreuses fonctionnalités de la plate-forme Web peuvent être utilisées pour optimiser votre expérience de chargement des polices. Consultez également le dépôt de recettes de polices Web de Zach Leatherman, car il est vraiment excellent.

Réduire les scripts bloquant le rendu

Il existe d'autres parties de notre application que nous pourrions transférer plus tôt dans la chaîne de téléchargement afin de fournir au moins une expérience utilisateur de base un peu plus tôt.

Sur la bande de la chronologie Lighthouse, vous pouvez voir que pendant ces premières secondes où toutes les ressources sont en cours de chargement, l'utilisateur ne voit pas vraiment de contenu.

Réduire les possibilités de feuilles de style bloquant le rendu
Fig. 24 : Réduire les possibilités de feuilles de style bloquant le rendu

Le téléchargement et le traitement des feuilles de style externes empêchent notre processus de rendu de progresser.

Nous pouvons essayer d'optimiser notre chemin de rendu critique en fournissant certains des styles un peu plus tôt.

Si nous extrayons les styles responsables de ce rendu initial et les insérons dans notre code HTML, le navigateur peut les afficher immédiatement sans attendre l'arrivée des feuilles de styles externes.

Dans le cas présent, nous avons utilisé un module NPM appelé Critical pour intégrer notre contenu critique dans index.html au cours d'une étape de compilation.

Bien que ce module ait effectué la majeure partie du travail pour nous, il a tout de même été un peu difficile de le faire fonctionner correctement sur différents itinéraires.

Si vous ne faites pas attention ou si la structure de votre site est très complexe, il peut être très difficile d'introduire ce type de modèle si vous n'avez pas prévu d'architecture du shell d'application dès le début.

C'est pourquoi il est si important de prendre en compte les performances dès le départ. Si vous ne concevez pas dès le départ pour des performances optimales, vous risquez de rencontrer des problèmes par la suite.

Au final, notre risque a payé, nous avons réussi à le faire fonctionner et l'application a commencé à diffuser du contenu beaucoup plus tôt, ce qui a considérablement amélioré notre temps de première peinture significative.

Résultat

Voici une longue liste d'optimisations de performances que nous avons appliquées à notre site. Examinons le résultat. Voici comment notre application se chargeait sur un appareil mobile de taille moyenne sur un réseau 3G, avant et après l'optimisation.

Le score de performance Lighthouse est passé de 23 à 91. C'est un bon progrès en termes de vitesse. Nous avons apporté toutes ces modifications en vérifiant en permanence et en suivant le rapport Lighthouse. Si vous souhaitez découvrir comment nous avons implémenté techniquement toutes les améliorations, n'hésitez pas à consulter notre dépôt, en particulier les PR qui y ont été ajoutées.

Performances prédictives : expériences utilisateur basées sur les données

Nous pensons que le machine learning représente une opportunité intéressante pour l'avenir dans de nombreux domaines. Nous espérons que cette idée, qui peut vraiment guider les expériences utilisateur que nous créons, incitera à davantage d'expérimentations à l'avenir.

Aujourd'hui, nous prenons de nombreuses décisions arbitraires sur ce que l'utilisateur pourrait vouloir ou avoir besoin, et donc sur ce qui mérite d'être préchargé, prétéléchargé ou pré-mis en cache. Si nous faisons le bon choix, nous pouvons hiérarchiser un petit nombre de ressources, mais il est très difficile de l'appliquer à l'ensemble du site Web.

Nous disposons actuellement de données qui nous permettent de mieux orienter nos optimisations. Grâce à l'API Google Analytics Reporting, nous pouvons examiner la page la plus populaire suivante et les pourcentages de sortie pour n'importe quelle URL de notre site, et ainsi tirer des conclusions sur les ressources à prioriser.

Si nous combinons cela à un bon modèle de probabilité, nous évitons de gaspiller les données de nos utilisateurs en préchargeant de manière excessive le contenu. Nous pouvons exploiter ces données Google Analytics, et utiliser le machine learning et des modèles tels que les chaînes de Markov ou les réseaux de neurones pour les implémenter.

Regroupement basé sur les données pour les applications Web
Fig. 25. Regroupement basé sur les données pour les applications Web

Pour faciliter ces tests, nous sommes heureux d'annoncer une nouvelle initiative baptisée Guess.js.

Guess.js
Fig. 26. Guess.js

Guess.js est un projet axé sur les expériences utilisateur basées sur les données pour le Web. Nous espérons qu'il vous inspirera à utiliser les données pour améliorer les performances Web et au-delà. Tout est disponible en Open Source dès aujourd'hui sur GitHub. Il a été créé en collaboration avec la communauté Open Source par Minko Gechev, Kyle Matthews de Gatsby, Katie Hempenius et plusieurs autres personnes.

Découvrez Guess.js et dites-nous ce que vous en pensez.

Résumé

Les scores et les métriques sont utiles pour améliorer la vitesse du Web, mais ce ne sont que des moyens, et non des objectifs en soi.

Nous avons tous déjà connu des chargements de pages lents en déplacement, mais nous avons désormais la possibilité d'offrir à nos utilisateurs des expériences plus agréables qui se chargent très rapidement.

L'amélioration des performances est un processus. De nombreux petits changements peuvent entraîner de grands gains. En utilisant les outils d'optimisation appropriés et en gardant un œil sur les rapports Lighthouse, vous pouvez offrir une expérience meilleure et plus inclusive à vos utilisateurs.

Remerciements particuliers à Ward Peeters, Minko Gechev, Kyle Mathews, Katie Hempenius, Dom Farolino, Yoav Weiss, Susie Lu, Yusuke Utsunomiya, Tom Ankers, Lighthouse et doodles Google.