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. Dans cet article, nous les expliquons en utilisant l'application Oodles Theater. Nous abordons également nos tests avec le chargement prédictif et 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 à trouver des solutions pour rendre le Web plus rapide et plus performant. Cela a donné lieu à 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 lors du développement de l'application Oodles Theater. Dans la seconde, nous parlerons de nos tests avec le chargement prédictif et de la nouvelle initiative Guess.js.

Le besoin de performances

Internet devient de plus en plus lourd chaque année. Si nous vérifions l'état du Web, nous pouvons voir qu'une page médiane sur mobile pèse environ 1,5 Mo, la majorité d'entre eux étant du code JavaScript et des 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 de rendu ou le code tiers superflu, contribuent à la complexité des performances.

La plupart des utilisateurs estiment que la vitesse est au sommet de la hiérarchie UX de leurs besoins. Ce n'est pas très surprenant, car vous ne pouvez pas faire beaucoup de choses tant que le chargement d'une page n'est pas terminé. Vous ne pouvez pas tirer de valeur de la page, vous ne pouvez pas admirer son esthétique.

Piramide 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 un secret pour vous : savoir par où commencer pour optimiser vos performances. Heureusement, il existe des outils qui peuvent vous aider.

Lighthouse : une base pour le workflow lié aux performances

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

Nous avons récemment lancé un grand nombre de nouveaux audits de performances qui sont vraiment utiles dans les workflows de développement quotidiens.

Nouveaux audits Lighthouse
Fig. 2. Nouveaux audits Lighthouse

Prenons un exemple pratique : 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. Le rapport Lighthouse a été le point de départ de l'optimisation.

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

D'après le rapport Lighthouse, les performances initiales de notre application étaient plutôt horribles. Sur un réseau 3G, l'utilisateur devait attendre 15 secondes pour que la première peinture significative ou 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 parfaitement cette évolution.

La page pesait environ 3,4 Mo.Nous avons désespérément eu besoin de réduire la quantité de graisse.

Cela a commencé notre premier défi en termes 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 blancs et les commentaires.

Gains générés par la minimisation
Fig. 4 : Réduire et compresser les fichiers JavaScript et CSS

Lighthouse met en évidence cette opportunité dans l'audit CSS et JavaScript non réduit. Nous utilisions webpack pour notre processus de compilation. Par conséquent, pour obtenir la minimisation, nous avons simplement utilisé le plug-in Uglify JS.

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

L'option 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 acceptent cette méthode dès le départ.

Nous utilisions Firebase Hosting pour héberger notre code, et Firebase active le gziping par défaut. Le simple fait d'héberger notre code sur un CDN raisonnable nous permet de l'obtenir sans frais.

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

Utiliser des stratégies de cache efficaces

L'étape suivante consistait à s'assurer que nous n'envoyons pas deux fois des ressources si cela n'était pas nécessaire.

L'audit de stratégie de mise en cache inefficace dans Lighthouse nous a permis de constater que nous pouvions optimiser nos stratégies de mise en cache pour atteindre cet objectif. 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 peut réutiliser les ressources qu'il a téléchargées auparavant.

Idéalement, vous devez essayer de mettre en cache autant de ressources de manière sécurisée que possible pendant la période la plus longue possible et fournir des jetons de validation pour une revalidation efficace des 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 les moins évidentes ? (par exemple, du code inutilisé).

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

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

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

Vous pouvez vérifier les statistiques de couverture de votre code dans les outils de développement, tant au niveau de l'exécution que du temps de chargement de votre application. Vous pouvez voir les deux grandes bandes rouges sur la capture d'écran en bas de l'écran. Plus de 95 % de notre CSS n'était pas utilisé, et beaucoup de JavaScript.

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

Si nous abandonnons l'adaptateur MVC, nos styles passent à 10 Ko.
Fig. 6 : Si nous intégrons l'adaptateur MVC, nos styles passent à 10 Ko.

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

Bien sûr, cela nous a permis d'augmenter notre score de performance, et le délai avant interactivité s'est nettement amélioré.

Cependant, dans de telles situations, il ne suffit pas de vérifier seulement vos métriques et vos scores. La suppression du code réel n'est jamais sans risque. Vous devez donc toujours surveiller les régressions potentielles.

95 % de notre code n'a pas été utilisé, alors que ces 5% restent quelque part. Apparemment, l'un de nos composants utilisait encore les styles de cette bibliothèque, à savoir les petites flèches du curseur de doodle. Mais 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.

Ainsi, si vous supprimez du code, assurez-vous simplement de mettre en place un workflow de test approprié pour vous prémunir d'éventuelles régressions visuelles.

Éviter d’énormes charges utiles de réseau

Nous savons que des ressources volumineuses peuvent ralentir le chargement des pages Web. Ils peuvent coûter de l'argent à nos utilisateurs et ils peuvent 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 que nous avions rencontré un problème avec certaines de nos charges utiles réseau à l'aide de l'audit Énorme charge utile réseau.

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

Nous avons constaté que le code en cours de transfert s'élevait à plus de 3 Mo, ce qui est très important, en particulier sur les mobiles.

Tout en haut de cette liste, Lighthouse indique que nous disposons d'un bundle de fournisseurs JavaScript contenant 2 Mo de code non compressé. Il s'agit également d'un problème mis en évidence par webpack.

Comme dit le dicton: la requête la plus rapide est celle qui n'est pas faite.

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

Dans notre cas, comme nous avons affaire à un grand nombre de bundles JavaScript, nous avons eu de la chance, car la communauté JavaScript dispose d'un large éventail d'outils d'audit pour les bundles.

Audit du bundle JavaScript
Fig. 9 : Audit des groupes 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 allés dans 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 incluait du code qui faisait référence à ce module.

Nous sommes ensuite passés à un autre outil, BundlePhobia. Il s'agit d'un outil qui vous permet de saisir le nom d'un package NPM et de connaître la taille estimée de sa taille réduite et compressée avec gzip. Nous avons trouvé une alternative intéressante pour le module slug que nous utilisions et qui ne pesait que 2, 2 ko.Nous avons donc augmenté cette valeur.

Cela a eu un impact important sur nos performances. Entre ce changement et la découverte d'autres opportunités pour 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 réduite de ces groupes au format gzip. Nous nous sommes rendu compte que cela valait vraiment la peine d'en faire un processus.

Par conséquent, essayez d'éliminer les téléchargements inutiles sur vos sites et applications. Faire un inventaire de vos éléments et mesurer leur impact sur les performances peut faire une grande différence. Par conséquent, assurez-vous de procéder à des audits assez réguliers.

Réduction du temps de démarrage JavaScript grâce au fractionnement du code

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

JavaScript est votre asset le plus cher. Sur mobile, si vous envoyez de grands groupes de code JavaScript, cela peut retarder le délai d'interaction des utilisateurs avec les composants de votre interface utilisateur. Cela signifie qu'ils peuvent appuyer sur l'interface utilisateur sans que rien ne se passe réellement. Il est donc important de comprendre pourquoi JavaScript est si onéreux.

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 tel qu'un ordinateur de bureau ou un ordinateur portable, voire un téléphone haut de gamme. Mais sur un téléphone mobile médian, ce processus peut prendre entre cinq et dix fois plus longtemps. C'est ce qui retarde l'interactivité, il est donc important pour nous d'essayer de la réduire.

Pour vous aider à détecter ces problèmes avec votre application, nous avons lancé un nouvel audit sur le temps de démarrage JavaScript dans Lighthouse.

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

Et dans le cas de l'application Oodle, il nous a indiqué que nous avions passé 1,8 seconde de temps au démarrage de JavaScript. Ce qui se produisait, c'est que nous importions de manière statique l'ensemble de nos routes et de tous nos composants dans un seul bundle JavaScript monolithique.

Une technique pour contourner ce problème consiste à diviser le code.

Le fractionnement par code, c'est comme une pizza

Cette notion de division du code consiste à ne pas donner à vos utilisateurs l'équivalent d'une pizza entière en JavaScript. Que se passerait-il si vous ne leur donniez qu'une part à la fois selon leurs besoins ?

Le fractionnement du code peut être appliqué au niveau d'une route ou d'un composant. Elle fonctionne très bien avec React et React Loadable, Vue.js, Angular, Polymer, Preact et de nombreuses autres bibliothèques.

Nous avons intégré la division du code dans notre application et nous sommes passés des importations statiques aux importations dynamiques, ce qui nous permet de charger le code de manière différée de manière asynchrone, selon 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. Elle en a fait 0,78 seconde, ce qui a rendu l'application 56% plus rapide.

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

Exploitez des concepts tels que le fractionnement de code, explorez des idées telles que le tree shaking (séisme d'arbre) 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 d'image

Dans l'application Oodle, nous utilisons de nombreuses images. Malheureusement, Lighthouse s'est montré bien moins enthousiaste que nous. En fait, nous n'avons pas réussi les trois audits liés aux images.

Nous avons oublié d'optimiser nos images, nous ne les dimensionnons pas correctement et nous pouvions aussi tirer profit d'autres formats d'image.

Audits des images
Fig. 14 : Audits des images Lighthouse

Nous avons commencé par optimiser nos images.

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

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

De cette façon, vous vous assurez que les images que vous ajouterez par la suite seront optimisées automatiquement. Certains CDN, comme Akamai, ou des solutions tierces comme Cloudinary, Fastly ou Uploadcare, proposent des solutions complètes d'optimisation des images. Vous pouvez donc simplement héberger vos images sur ces services.

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

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

Notre fichier PNG d'arrière-plan a été signalé dans Webpack comme étant grand, et à juste titre. Après l'avoir correctement dimensionné dans la fenêtre d'affichage et exécuté 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 la taille globale de la page.

Utiliser le format approprié pour les contenus animés

Les GIF peuvent coûter très cher. É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 approprié vous permet de réaliser des économies importantes en termes de taille de fichier.

Dans l'application Oodle, nous utilisions un GIF comme séquence d'introduction sur la page d'accueil. D'après 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 bien trop important pour un site Web raisonnable.Au lieu de cela, nous l'avons transformé en un élément vidéo avec deux fichiers sources, au format MP4 et WebM pour une compatibilité avec un navigateur plus large.

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 le 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 à votre place.

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. Cela nous a amenés à environ 1 Mo.

Toutefois, 1 Mo est une ressource importante pour pousser le fil, en particulier pour un utilisateur dont la bande passante est limitée. Heureusement, nous pourrions utiliser l'API Effective Type pour nous rendre compte que leur bande passante est lente, et leur donner un JPEG bien plus petit.

Cette interface utilise le délai aller-retour effectif et les valeurs de réduction pour estimer le type de réseau utilisé par l'utilisateur. Il renvoie simplement une chaîne indiquant que la connexion 2G, 2G, 3G ou 4G est lente. Ainsi, en fonction de cette valeur, si l'utilisateur est en dessous de la 4G, nous pouvons remplacer l'élément vidéo par l'image.

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

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

Images hors écran avec chargement différé

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

Lighthouse signale ce comportement dans l'audit des images hors écran. Vous pouvez également le voir par vous-même dans le panneau "Réseau" des outils de développement. Si vous voyez beaucoup d'images entrantes alors que seules quelques-unes sont visibles sur la page, vous pouvez peut-être envisager de les charger lentement.

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 le 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 intelligente, car elle suit non seulement les changements de visibilité de l'élément, mais elle précharge également de manière proactive les éléments situés à proximité de la vue pour une expérience utilisateur optimale. Il propose également une intégration facultative de IntersectionObserver, ce qui vous permet d'effectuer des recherches de visibilité très efficaces.

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

Aider le navigateur à fournir les ressources critiques en amont

Tous les octets envoyés via le câble au navigateur n'ont pas le même degré d'importance, et le navigateur le sait. De nombreux navigateurs appliquent des méthodes heuristiques pour décider de ce qu'ils doivent extraire en premier. Parfois, le code CSS est récupéré avant les images ou les scripts.

En tant qu'auteurs de la page, nous pourrions être utiles pour indiquer au navigateur ce qui est vraiment important pour nous. Heureusement, ces deux dernières années, les fournisseurs de navigateurs ont ajouté un certain nombre de fonctionnalités pour nous aider dans ce domaine, par exemple des indices de ressources comme link rel=preconnect, preload ou prefetch.

Ces fonctionnalités intégrées à la plate-forme Web aident le navigateur à récupérer la bonne chose au bon moment. Elles peuvent également s'avérer un peu plus efficaces que certaines approches de chargement personnalisées basées sur la logique qui sont effectuées à l'aide d'un script.

Voyons comment Lighthouse nous guide vers l'utilisation efficace de certaines de ces fonctionnalités.

La première chose que Lighthouse nous dit de faire est d'éviter plusieurs allers-retours coûteux vers n'importe quel point de départ.

Évitez les allers-retours multiples et coûteux vers n&#39;importe quel point de départ
Fig. 17 : Évitez les allers-retours multiples et coûteux vers n'importe quel point de départ.

Dans le cas de l'application Oodle, nous utilisons énormément Google Fonts. Chaque fois que vous déposez une feuille de style Google Fonts dans votre page, elle connecte jusqu'à deux sous-domaines. Ce que Lighthouse nous dit, c'est que si nous pouvions chauffer cette connexion, nous pourrions gagner jusqu'à 300 millisecondes dans notre temps de connexion initial.

Grâce à la préconnexion "Link Re", nous pouvons masquer efficacement cette latence de connexion.

Cela peut avoir un impact très important, en particulier avec Google Fonts, où notre CSS font face est hébergé sur googleapis.com et nos ressources de police sont hébergées sur Gstatic. Nous avons donc appliqué cette optimisation et réduit de quelques centaines de millisecondes.

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

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

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

Lighthouse nous indique à présent que nous devrions lancer le préchargement de nos principales ressources de police 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 sur votre page est assez catastrophique.

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 pour votre page, le navigateur doit d'abord récupérer votre code HTML, analyser votre code CSS, puis récupérer vos polices Web beaucoup plus tard.

Avec le préchargement "link rel", dès que le navigateur a analysé votre code HTML, il peut commencer à récupérer ces polices Web beaucoup plus tôt. Dans le cas de notre application, l'affichage du texte à l'aide de nos polices Web nous a permis de gagner une seconde.

Ce n'est pas aussi simple que cela si vous essayez de précharger des polices à l'aide de Google Fonts. Il y a un piège.

L'équipe Google Fonts met à jour assez régulièrement les URL Google Fonts que nous spécifions sur les polices dans nos feuilles de style. Ces URL peuvent expirer ou être mises à jour régulièrement. Par conséquent, si vous souhaitez contrôler totalement l'expérience de chargement des polices, vous pouvez auto-héberger vos polices Web. Cela peut être utile parce qu'il vous donne accès à des éléments comme le préchargement de lien.

Dans notre cas, nous avons trouvé l'outil d'aide Google Web Fonts très utile, car il nous permet de mettre certaines de ces polices Web hors connexion et de les configurer localement. Nous vous conseillons donc d'utiliser cet outil.

Que vos ressources critiques utilisent des polices Web ou du code JavaScript, essayez d'aider le navigateur à exploiter au plus vite vos ressources essentielles.

Expérimental: Indicateurs de priorité

Nous avons quelque chose de spécial à vous faire 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 pour navigateur, appelée "indices prioritaires".

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, avec les valeurs low, high ou auto.

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

Dans le cas de notre application Oodle, nous avons pu exploiter une opportunité d'optimisation.

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, ce que faisait le navigateur, nous avions ce carrousel d'images avec tous nos doodles, et le navigateur récupérait toutes les images au tout début du carrousel avec une priorité élevée dès le début. 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, celles au premier plan sur très élevée. Cela a eu un impact de deux secondes sur une 3G lente, et la rapidité avec laquelle nous avons pu récupérer et afficher ces images. C'est donc une expérience positive.

Nous espérons déployer cette fonctionnalité dans Canary dans quelques semaines. Gardez un œil sur cette fonctionnalité.

Adopter une stratégie de chargement des polices Web

La typographie est essentielle à une bonne conception. Si vous utilisez des polices Web, idéalement, vous ne souhaitez pas bloquer le rendu de votre texte, et vous ne voulez certainement pas afficher de texte invisible.

Nous mettons en évidence ce point dans Lighthouse maintenant, avec l'audit permettant d'é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 police de caractères, vous laissez le navigateur décider 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, puis la remplaceront par la police une fois qu'elle aura été téléchargée.

Nous essayons d'éviter ce texte invisible. Dans ce cas, nous n'aurions pas pu voir les doodles classiques de la semaine si la police Web avait pris trop de temps. Heureusement, la nouvelle fonctionnalité font-display vous permet de 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écider du mode d'affichage ou de remplacement des polices Web en fonction du temps nécessaire à leur échange.

Dans ce cas, nous utilisons font display swap. L'échange donne à la police une période de bloc de zéro seconde et une période d'échange infinie. Cela signifie que le navigateur va dessiner votre texte assez immédiatement avec une police de remplacement si le chargement de la police prend un certain temps. Et il l'échangera une fois la police disponible.

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

Résultat d&#39;affichage de la police
Fig. 23. Résultat d'affichage des polices

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

Il existe de nombreuses fonctionnalités de la plate-forme Web que vous pouvez utiliser pour optimiser votre expérience de chargement des polices, mais vous pouvez également consulter le dépôt Web Font Recipes de Zach Warmman, qui est vraiment très utile.

Réduire les scripts qui bloquent l'affichage

Nous pourrions ajouter d'autres parties de notre application plus tôt dans la chaîne de téléchargement afin d'offrir au moins une expérience utilisateur de base un peu plus tôt.

Sur la barre de chronologie Lighthouse, vous pouvez voir que pendant ces premières secondes, lorsque toutes les ressources sont en cours de chargement, l'utilisateur ne peut réellement voir aucun contenu.

Réduire le nombre de feuilles de style bloquant l&#39;affichage
Fig. 24 : Réduire le nombre de feuilles de style bloquant l'affichage

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

Nous pouvons essayer d'optimiser le chemin critique du rendu en livrant certains styles un peu plus tôt.

Si nous extrayons les styles responsables de ce rendu initial et les incorporons dans 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 critique dans le fichier index.html lors d'une étape de compilation.

Même si ce module a fait le plus gros du travail pour nous, il était encore un peu difficile de le faire fonctionner correctement sur différents itinéraires.

Si vous n'y faites pas attention ou si la structure de votre site est vraiment complexe, il peut être très difficile d'introduire ce type de modèle si vous n'aviez pas prévu d'utiliser l'architecture de shell d'application dès le départ.

C'est pourquoi il est si important de prendre en compte les performances dès le début. Si vous ne concevez pas pour les performances dès le départ, il est fort probable que vous rencontriez des problèmes plus tard.

En fin de compte, notre risque a porté ses fruits, 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é le premier temps de rendu significatif.

Le résultat

Nous avons appliqué une longue liste d'optimisations des performances à notre site. Examinons le résultat. Voici comment notre application se charge 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 très bon progrès en termes de vitesse. Toutes ces modifications ont été motivées par la vérification et le suivi continus du rapport Lighthouse. Si vous souhaitez découvrir comment nous avons techniquement mis en œuvre toutes les améliorations, n'hésitez pas à consulter notre dépôt, en particulier les demandes d'extraction.

Prédictions de performances : expériences utilisateur basées sur les données

Nous sommes convaincus que le machine learning représente une opportunité passionnante pour l'avenir dans de nombreux domaines. Nous espérons que d'autres tests seront menés à bien à l'avenir : les données réelles peuvent réellement guider les expériences utilisateur que nous créons.

Aujourd'hui, nous prenons de nombreuses décisions arbitraires concernant les souhaits ou les besoins de l'utilisateur, et donc ce qui vaut la peine d'être préchargé, préchargé ou mis en cache. Si nous devinons que c'est exact, nous sommes en mesure de hiérarchiser une petite quantité de ressources, mais il est vraiment difficile de les étendre à l'ensemble du site Web.

Nous disposons de données qui nous permettent aujourd'hui de mieux orienter nos optimisations. Grâce à l'API de création de rapports Google Analytics, nous pouvons consulter la première page suivante et les pourcentages de sortie de n'importe quelle URL de notre site, et 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 de manière agressive le contenu. Nous pouvons exploiter ces données Google Analytics, et utiliser des modèles de machine learning et des modèles tels que les chaînes de Markov ou le réseau de neurones pour mettre en œuvre de tels modèles.

Offres groupées basées sur les données pour les applications Web
Fig. 25 : Offres groupées basées sur les données pour les applications Web

Pour faciliter ces tests, nous avons le plaisir d'annoncer le lancement de Guess.js, une nouvelle initiative.

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 les données pour améliorer les performances Web et aller au-delà. C'est un outil Open Source disponible sur GitHub aujourd'hui. Il a été conçu en collaboration avec la communauté Open Source par Minko Gechev, Kyle Matthews de Gatsby, Katie Hempenius et plusieurs autres.

Découvrez Guess.js et donnez-nous votre avis.

Résumé

Les scores et les métriques sont utiles pour améliorer la vitesse du Web, mais ce ne sont que des moyens, pas les objectifs eux-mêmes.

Nous avons tous constaté une lenteur du chargement des pages lors de nos déplacements, mais nous avons maintenant la possibilité d'offrir à nos utilisateurs une expérience plus agréable qui se charge très rapidement.

Améliorer les performances n'est pas une mince affaire. De nombreux petits changements peuvent procéder à des gains importants. En utilisant les bons outils d'optimisation et en surveillant les rapports Lighthouse, vous pouvez offrir une expérience de meilleure qualité et plus inclusive.

Nous remercions tout particulièrement Ward Peeters, Minko Gechev, Kyle Mathews, Katie Hempenius, Dom Farolino, Yoav Weiss, Susie Lu, Yusuke Utsunomiya, Tom Ankers, Lighthouse et les doodles Google.