Améliorer les performances Web facilement – Édition Google I/O 2018

Lors de Google I/O 2018, nous avons présenté un ensemble d'outils, de bibliothèques et de techniques d'optimisation qui facilitent l'amélioration des performances Web. Nous allons les expliquer en utilisant l'application The Oodles Theater. Nous allons également parler de nos expériences avec le chargement prédictif et de la nouvelle initiative Guess.js.

Ewa Gasperowicz

Au cours de l'année écoulée, nous avons été très occupés à essayer de trouver comment rendre le Web plus rapide et plus performant. Cela a conduit à de nouveaux outils, approches et bibliothèques que nous aimerions partager avec vous dans cet article. Dans la première partie, nous vous présenterons quelques techniques d'optimisation que nous avons utilisées en pratique lors du développement de l'application Oodles Theater. Dans la deuxième partie, nous parlerons de nos expériences avec le chargement prédictif et de la nouvelle initiative Guess.js.

Nécessité de performances

Chaque année, Internet devient de plus en plus lourd. Si nous vérifions l'état du Web, nous pouvons constater qu'une page mobile médiane pèse environ 1,5 Mo, dont la majorité est constituée de 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é des performances.

La plupart des utilisateurs considèrent la vitesse comme le besoin le plus important dans la hiérarchie des besoins de l'UX. Ce n'est pas très surprenant, car vous ne pouvez pas faire grand-chose tant qu'une page n'est pas complètement chargée. Vous ne pouvez pas tirer de valeur de la page ni admirer son esthétique.

Pyramide de la hiérarchie de l'UX
Fig. 1 Quelle est l'importance de la vitesse pour les utilisateurs ? (Speed Matters, Vol. 3)

Nous savons que les performances sont importantes pour les utilisateurs, mais il peut être difficile de savoir par où commencer pour les optimiser. Heureusement, il existe des outils qui peuvent vous aider.

Lighthouse : une base pour le workflow de performances

Lighthouse fait partie des outils pour les développeurs Chrome. Il vous permet d'auditer votre site Web et vous donne des conseils pour l'améliorer.

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

Nouveaux audits Lighthouse
Fig. 2 Nouveaux audits Lighthouse

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

Lors de la création de l'application, nous avons veillé à ce qu'elle soit aussi performante que possible. Le point de départ de l'optimisation était 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'indiquées dans le rapport Lighthouse, étaient plutôt médiocres. Sur un réseau 3G, l'utilisateur devait attendre 15 secondes pour que le premier affichage utile se produise 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 sa taille.

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 sans risque : les espaces et les commentaires.

Gains obtenus grâce à la réduction
Fig. 4 : Réduire la taille et compresser le code JavaScript et CSS

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

La minification est une tâche courante. Vous devriez donc pouvoir trouver une solution prête à l'emploi, quel que soit le processus de compilation que vous utilisez.

L'audit Activer la compression de texte est également utile dans ce domaine. Il n'y a aucune raison d'envoyer des fichiers non compressés, et la plupart des CDN prennent en charge cette fonctionnalité par défaut de nos jours.

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

Bien que gzip soit une méthode de compression très populaire, d'autres mécanismes comme Zopfli et Brotli gagnent également en popularité. Brotli est compatible avec la plupart des navigateurs. Vous pouvez utiliser un binaire pour précompresser vos ressources avant de les envoyer au serveur.

Utiliser des règles de cache efficaces

L'étape suivante consistait à nous assurer de ne pas envoyer de ressources deux fois si ce n'était pas nécessaire.

L'audit Stratégie 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 que lors d'une visite répétée, l'utilisateur puisse réutiliser les ressources qu'il avait téléchargées auparavant.

Dans l'idéal, vous devez mettre en cache le plus de ressources 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 qui ont été 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, le code inutilisé.

Couverture du 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 surtout si vous travaillez sur votre application pendant une longue période, si votre équipe ou vos dépendances changent, et parfois une bibliothèque orpheline est laissée pour compte. C'est exactement ce qui nous est arrivé.

Au début, nous utilisions la bibliothèque Material Components pour prototyper rapidement notre application. Au fil du temps, nous avons opté pour une apparence plus personnalisée et avons complètement oublié cette bibliothèque. Heureusement, la vérification de la couverture du code nous a aidés à le redécouvrir dans notre bundle.

Vous pouvez consulter les statistiques de couverture du code dans les outils de développement, à la fois pour l'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 partie du JavaScript.

Lighthouse a également détecté ce problème dans l'audit des règles CSS inutilisées. Il a montré une économie potentielle de plus de 400 ko. Nous sommes donc retournés à notre code et avons supprimé les parties JavaScript et CSS de cette bibliothèque.

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

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

Bien sûr, notre score de performances a augmenté, et le temps avant interactivité s'est considérablement amélioré.

Toutefois, avec des modifications comme celle-ci, il ne suffit pas de vérifier vos métriques et vos scores. La suppression de code réel n'est jamais sans risque. Vous devez donc toujours être à l'affût des régressions potentielles.

Notre code n'a pas été utilisé dans 95 % des cas. Il reste donc 5 % quelque part. Apparemment, l'un de nos composants utilisait encore les styles de cette bibliothèque : les petites flèches du curseur de doodle. Cependant, comme il était si petit, nous pouvions simplement réintégrer manuellement ces styles dans les boutons.

Les boutons ne fonctionnent pas en raison d'une bibliothèque manquante
Fig. 7. Un composant utilisait encore la bibliothèque supprimée.

Par conséquent, si vous supprimez du code, assurez-vous de disposer d'un workflow de test approprié pour vous aider à vous prémunir contre d'éventuelles régressions visuelles.

É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 pu détecter un problème avec certains de nos payloads réseau à l'aide de l'audit Payload réseau énorme.

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

Nous avons constaté que plus de 3 Mo de code étaient envoyés, ce qui est beaucoup, surtout sur mobile.

En haut de cette liste, Lighthouse a souligné 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 le dit l'adage : la requête la plus rapide est celle qui n'est pas envoyée.

Idéalement, vous devriez mesurer la valeur de chaque élément que vous diffusez à vos utilisateurs, mesurer les performances de ces éléments et décider s'il vaut la peine de les inclure dans l'expérience initiale. En effet, ces éléments peuvent parfois être différés, chargés de manière différée ou traités pendant les périodes 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
Fig. 9 : Audit des bundles JavaScript

Nous avons commencé par l'analyseur de bundle webpack, qui nous a indiqué que nous incluions une dépendance appelée "unicode", qui représentait 1,6 Mo de JavaScript analysé, ce qui est beaucoup.

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

Nous sommes ensuite passés à un autre outil, BundlePhobia. Cet outil vous permet de saisir le nom de n'importe quel package NPM et de voir la taille estimée de sa version minifiée et compressée. Nous avons trouvé une bonne alternative au module de slug que nous utilisions, qui ne pesait que 2,2 ko.Nous avons donc opté pour cette solution.

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

Nous avons constaté une amélioration globale de 65 % une fois que vous avez pris en compte la taille compressée et minimisée de ces bundles. Nous avons constaté que ce processus valait vraiment la peine d'être mis en place.

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 faire une grande différence. Assurez-vous donc d'auditer vos composants assez régulièrement.

Réduire le temps de démarrage de JavaScript grâce à la division du code

Bien que les grandes charges utiles réseau puissent avoir un impact important sur notre application, il existe un autre élément qui peut avoir un impact encore plus important : JavaScript.

JavaScript est votre ressource la plus coûteuse. Sur mobile, si vous envoyez de gros bundles JavaScript, cela peut retarder le moment où vos utilisateurs pourront interagir avec les composants de votre interface utilisateur. Cela signifie qu'ils peuvent appuyer sur l'UI sans qu'il se passe quoi que ce soit. Il est donc important pour nous de comprendre pourquoi JavaScript coûte si cher.

Voici comment un navigateur traite JavaScript.

Traitement JavaScript
Fig. 10. Traitement JavaScript

Nous devons tout 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, un ordinateur portable ou même un téléphone haut de gamme. Mais sur un téléphone mobile moyen, ce processus peut prendre cinq à dix fois plus de temps. C'est ce qui retarde l'interactivité. Il est donc important pour nous d'essayer de réduire ce temps.

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

Temps de démarrage de JavaScript
Fig. 11. Audit du temps de démarrage JavaScript

Dans le cas de l'application Oodle, il nous a indiqué que nous avions passé 1,8 seconde dans le démarrage de JavaScript. En fait, nous importions statiquement toutes nos routes et tous nos composants dans un bundle JavaScript monolithique.

Une technique pour contourner ce problème consiste à utiliser le fractionnement du code.

Le fractionnement du code, c'est comme une pizza

Le fractionnement du code consiste à ne pas fournir aux utilisateurs l'intégralité du code JavaScript, mais plutôt une tranche à la fois, selon leurs besoins.

La séparation du code peut être appliquée au niveau d'une route ou d'un composant. Il fonctionne parfaitement avec React et React Loadable, Vue.js, Angular, Polymer, Preact et de nombreuses autres bibliothèques.

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

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

Cela a permis de réduire la taille de nos bundles, mais aussi de diminuer le temps de démarrage de notre JavaScript. Il est passé à 0,78 seconde, ce qui a permis d'accélérer l'application de 56 %.

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

Profitez de concepts tels que le fractionnement du code, explorez des idées comme le tree shaking 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 était beaucoup moins enthousiaste que nous. En fait, nous avons échoué à tous les audits liés aux images.

Nous avons oublié d'optimiser nos images, nous ne les avons pas redimensionnées correctement et nous pourrions également gagner en utilisant d'autres formats d'image.

Audits d'images
Fig. 14 : Audits d'images Lighthouse

Nous avons commencé par optimiser nos images.

Pour une 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, avec des bibliothèques comme imagemin.

Vous vous assurez ainsi que les images ajoutées à l'avenir seront optimisées automatiquement. Certains CDN, comme Akamai ou des solutions tierces telles que Cloudinary, Fastly ou Uploadcare, proposent des solutions d'optimisation d'images complètes. Vous pouvez donc aussi simplement héberger vos images sur ces services.

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

Avant et après l'optimisation
Fig. 15 : Avant et après l'optimisation

Notre PNG d'arrière-plan a été signalé comme volumineux dans webpack, et à juste titre. Après l'avoir redimensionné correctement à la fenêtre d'affichage et l'avoir exécuté dans ImageOptim, nous sommes passés à 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é au 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, ce qui est beaucoup trop pour un site Web raisonnable.Nous l'avons donc transformé en élément vidéo avec deux fichiers sources : un fichier MP4 et un fichier WebM pour une compatibilité plus large avec les navigateurs.

Remplacer les GIF animés par des vidéos
Fig. 16 : Remplacer les GIF animés par des vidéos

Nous avons utilisé l'outil FFmpeg pour convertir notre GIF animé en fichier 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

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

Toutefois, 1 Mo est une ressource importante à transférer, en particulier pour un utilisateur dont la bande passante est limitée. Heureusement, nous avons pu utiliser l'API Effective Type pour nous rendre compte qu'ils disposaient d'une bande passante lente et leur fournir un JPEG beaucoup plus petit.

Cette interface utilise les valeurs de temps aller-retour effectif et de temps d'arrêt pour estimer le type de réseau utilisé par l'utilisateur. Elle renvoie simplement une chaîne de caractères : "slow 2G", "2G", "3G" ou "4G". Ainsi, en fonction de cette valeur, si l'utilisateur est sur un réseau inférieur à 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 signalera ce comportement dans l'audit des images hors écran. Vous pouvez également le constater vous-même dans le panneau "Réseau" des outils de développement. Si vous constatez qu'un grand nombre d'images sont chargées alors que seules quelques-unes sont visibles sur la page, vous pouvez envisager de les charger de manière différée.

Le chargement différé n'est pas encore pris en charge de manière native 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 différé à 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 se contente pas de suivre les changements de visibilité de l'élément, mais il précharge également de manière proactive les éléments proches de la vue pour une expérience utilisateur optimale. Il offre également une intégration facultative de IntersectionObserver, qui vous permet d'effectuer des recherches de visibilité très efficaces.

Après ce changement, nos images sont récupérées à la demande. Si vous souhaitez en savoir plus sur ce sujet, consultez images.guide, une ressource très pratique et complète.

Aider le navigateur à fournir rapidement les ressources critiques

Tous les octets envoyés au navigateur n'ont pas la même importance, et le navigateur le sait. De nombreux navigateurs disposent d'heuristiques pour déterminer ce qu'ils doivent récupérer en premier. Il arrive donc qu'ils récupèrent le CSS avant les images ou les scripts.

Il pourrait ê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 les indications de ressources comme link rel=preconnect, preload ou prefetch.

Ces fonctionnalités ajouté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 approches de chargement personnalisées basées sur la logique et effectuées à l'aide de scripts.

Voyons comment Lighthouse nous guide pour utiliser efficacement certaines de ces fonctionnalités.

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

Éviter les allers-retours multiples et coûteux vers n&#39;importe quelle origine
Fig. 17 : Évitez 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 déposez une feuille de style Google Fonts sur votre page, elle se connecte à un ou deux sous-domaines. Lighthouse nous indique que si nous parvenions à préchauffer cette connexion, nous pourrions gagner jusqu'à 300 millisecondes sur notre temps de connexion initial.

En tirant parti de la préconnexion link rel, nous pouvons masquer efficacement cette latence de connexion.

Cela peut avoir un impact considérable, en particulier avec Google Fonts, où notre CSS de famille de polices est hébergé sur googleapis.com et nos ressources de police sur Gstatic. Nous avons donc appliqué cette optimisation et gagné quelques centaines de millisecondes.

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

Demandes de préchargement de clés
Fig. 18 Précharger les demandes de clé

<link rel=preload> est très puissant. Il indique au navigateur qu'une ressource est nécessaire dans le cadre de la navigation actuelle et tente de faire en sorte que le navigateur la récupère le plus rapidement possible.

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

Le préchargement d'une police Web se présente comme suit : 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, tel que woff2.

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

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

Normalement, sans utiliser le préchargement link 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, beaucoup plus tard, récupérer vos polices Web.

Grâce au préchargement de la relation de lien, le navigateur peut commencer à récupérer ces polices Web beaucoup plus tôt, dès qu'il a analysé votre code HTML. Dans le cas de notre application, cela nous a permis de gagner une seconde sur le temps nécessaire pour afficher du texte à l'aide de nos polices Web.

Si vous essayez de précharger des polices à l'aide de Google Fonts, la procédure n'est pas aussi simple.

Les URL Google Fonts que nous spécifions sur nos visages de police dans nos feuilles de style sont mises à jour assez régulièrement par l'équipe Fonts. Ces URL peuvent expirer ou être mises à jour régulièrement. Par conséquent, si vous souhaitez contrôler entièrement l'expérience de chargement de vos polices, nous vous suggérons d'héberger vous-même vos polices Web. Cela peut être très utile, car cela vous donne accès à des éléments tels que le préchargement de la balise link rel.

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

Que vous utilisiez des polices Web comme ressources essentielles ou qu'il s'agisse de JavaScript, essayez d'aider le navigateur à fournir vos ressources essentielles le plus rapidement possible.

Expérimental : conseils de priorité

Nous avons une surprise à vous annoncer aujourd'hui. En plus des fonctionnalités telles que les indications de ressources et le préchargement, nous avons travaillé sur une toute nouvelle fonctionnalité expérimentale du navigateur que nous appelons "indications de priorité".

Définir la priorité du contenu initialement visible
Fig. 20 : Indicateurs 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 (importance) avec les valeurs "low" (faible), "high" (élevée) ou "auto" (automatique).

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

Dans le cas de notre application Oodle, cela nous a permis de trouver un endroit pratique où nous pouvions optimiser.

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

Avant d'ajouter le chargement différé à nos images, le navigateur récupérait toutes les images au tout début du carrousel avec une priorité élevée. Malheureusement, les images au milieu du carrousel étaient les plus importantes pour l'utilisateur. Nous avons donc défini l'importance de ces images d'arrière-plan 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 vitesse à laquelle nous avons pu récupérer et afficher ces images sur une connexion 3G lente. C'est donc une expérience positive.

Nous espérons proposer cette fonctionnalité dans Canary d'ici quelques semaines. Restez à l'affût !

Adopter une stratégie de chargement des polices Web

La typographie est essentielle à une bonne conception. Si vous utilisez des polices Web, l'idéal est de ne pas bloquer le rendu de votre texte et, surtout, de ne pas afficher de texte invisible.

Nous le mettons désormais en évidence 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 type "font-face", vous laissez le navigateur décider de ce qu'il doit faire si la récupération de cette police Web prend beaucoup de temps. Certains navigateurs attendent jusqu'à trois secondes avant de revenir à une police système, puis la remplacent par la police une fois qu'elle est téléchargée.

Nous essayons d'éviter ce texte invisible. Dans ce cas, nous n'aurions pas pu voir les Doodles classiques de cette semaine si la police Web avait mis trop de temps à se charger. Heureusement, grâce à une nouvelle fonctionnalité appelée font-display, vous pouvez mieux contrôler 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 qu'il leur faut pour être remplacées.

Dans ce cas, nous utilisons l'échange d'affichage de la police. "Swap" attribue à la typographie une période de blocage de zéro seconde et une période d'échange infinie. Cela signifie que le navigateur va dessiner votre texte assez rapidement avec une police de secours si la police met du temps à se charger. Il va la remplacer une fois que la typographie 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 général, si vous utilisez des polices Web, comme une grande partie du Web, mettez en place une bonne stratégie de chargement des polices Web.

Vous pouvez utiliser de nombreuses fonctionnalités de la plate-forme Web pour optimiser l'expérience de chargement des polices. Consultez également le dépôt Web Font Recipes de Zach Leatherman, car il est vraiment excellent.

Réduire les scripts qui bloquent le rendu

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

Sur la bande chronologique Lighthouse, vous pouvez voir que pendant ces premières secondes où toutes les ressources se chargent, l'utilisateur ne peut pas vraiment voir de contenu.

Réduire l&#39;opportunité de feuilles de style bloquant le rendu
Fig. 24 : Opportunité "Réduire les feuilles de style qui bloquent 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 styles un peu plus tôt.

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

Dans notre cas, nous avons utilisé un module NPM appelé Critical pour intégrer notre contenu essentiel dans index.html lors d'une étape de compilation.

Bien que ce module ait fait le gros du travail pour nous, il était encore un peu délicat de le faire fonctionner correctement sur différentes routes.

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 App Shell dès le début.

C'est pourquoi il est si important de prendre en compte les performances dès le début. Si vous ne concevez pas votre application pour les performances dès le début, vous risquez fortement de rencontrer des problèmes plus tard.

Finalement, notre risque a payé. Nous avons réussi à faire fonctionner l'application, qui a commencé à diffuser du contenu beaucoup plus tôt, ce qui a considérablement amélioré notre temps de premier rendu significatif.

Résultat

Nous avons appliqué une longue liste d'optimisations des performances à notre site. Examinons le résultat. Voici comment notre application s'est chargée sur un appareil mobile de taille moyenne sur un réseau 3G, avant et après l'optimisation.

Le score de performances Lighthouse est passé de 23 à 91. C'est une belle progression en termes de vitesse. Toutes ces modifications ont été apportées en vérifiant et en suivant en permanence le rapport Lighthouse. Si vous souhaitez découvrir comment nous avons techniquement implémenté toutes les améliorations, n'hésitez pas à consulter notre dépôt, en particulier les demandes d'extraction qui y ont été déposées.

Performances prédictives : des 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 l'idée selon laquelle les données réelles peuvent réellement guider les expériences utilisateur que nous créons suscitera davantage d'expérimentations à l'avenir.

Aujourd'hui, nous prenons de nombreuses décisions arbitraires concernant ce que l'utilisateur peut vouloir ou avoir besoin, et donc ce qui vaut la peine d'être préchargé, prérendu ou pré-mis en cache. Si nous devinons correctement, nous pouvons hiérarchiser une petite quantité de ressources, mais il est très difficile de l'étendre à l'ensemble du site Web.

Nous disposons de données qui nous permettent d'optimiser nos campagnes plus efficacement. L'API Google Analytics Reporting nous permet d'examiner les pages suivantes les plus consultées et les pourcentages de sortie pour n'importe quelle URL de notre site. Nous pouvons ainsi tirer des conclusions sur les ressources à privilégier.

Si nous combinons cela avec un bon modèle de probabilité, nous évitons de gaspiller les données de nos utilisateurs en préchargeant trop de contenu de manière agressive. Nous pouvons tirer parti de 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 implémenter de tels modèles.

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 que nous appelons 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 incitera à explorer l'utilisation des données pour améliorer les performances Web et aller au-delà. Il s'agit d'un projet Open Source disponible dès aujourd'hui sur GitHub. Il a été développé en collaboration avec la communauté Open Source par Minko Gechev, Kyle Matthews de Gatsby, Katie Hempenius et bien d'autres.

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 ils ne sont qu'un moyen, et non un objectif en soi.

Nous avons tous déjà rencontré des problèmes de chargement lent des pages en déplacement. Nous avons désormais l'opportunité d'offrir à nos utilisateurs des expériences plus agréables qui se chargent très rapidement.

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

Merci tout particulièrement à : Ward Peeters, Minko Gechev, Kyle Mathews, Katie Hempenius, Dom Farolino, Yoav Weiss, Susie Lu, Yusuke Utsunomiya, Tom Ankers, Lighthouse et Google Doodles.