Lors de la conférence 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 les expliquons ici à l'aide de l'application Oodles Theater. Nous parlons également de nos tests de chargement prédictif et de la nouvelle initiative Guess.js.
Au cours de l'année écoulée, nous avons travaillé d'arrache-pied pour trouver comment rendre le Web plus rapide et plus performant. Cela a conduit à de nouveaux outils, approches et bibliothèques que nous souhaitons partager avec vous dans cet article. Dans la première partie, nous vous présenterons quelques techniques d'optimisation que nous avons utilisées lors du développement de l'application Oodles Theater. Dans la deuxième partie, nous parlerons de nos tests de 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é de ce poids étant constitué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 de l'affichage ou le code tiers superflu, contribuent à compliquer les performances.
La plupart des utilisateurs considèrent la vitesse comme l'élément le plus important de l'expérience utilisateur. Cela n'est pas très surprenant, car vous ne pouvez pas faire grand-chose tant que le chargement d'une page n'est pas terminé. Vous ne pouvez pas tirer de valeur de la page, ni admirer son esthétique.
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 des 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é un certain nombre de nouveaux audits de performances qui sont très utiles dans le workflow de développement quotidien.
Voyons comment vous pouvez en profiter à l'aide d'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 jeu ou deux.
Lors de la création de l'application, nous voulions nous assurer qu'elle était aussi performante que possible. Le point de départ de l'optimisation était un rapport Lighthouse.
Les performances initiales de notre application, telles qu'elles apparaissent dans le rapport Lighthouse, étaient assez médiocres. Sur un réseau 3G, l'utilisateur devait attendre 15 secondes avant le First Meaningful Paint ou avant de pouvoir interagir avec l'application. Lighthouse a mis en évidence de nombreux problèmes sur notre site, et le score de performances global de 23 reflétait exactement cela.
La page pesait environ 3,4 Mo. Nous devions absolument réduire sa taille.
C'est ainsi que nous avons relevé notre premier défi d'optimisation des 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 blancs et les commentaires.
Lighthouse met en évidence cette opportunité dans l'audit des fichiers CSS et JavaScript non minifiés. Nous utilisions webpack pour notre processus de compilation. Pour obtenir la minimisation, nous avons simplement utilisé le plug-in Uglify JS.
La minimisation est une tâche courante. Vous devriez donc pouvoir trouver une solution prête à l'emploi pour 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 sont compatibles avec cette fonctionnalité.
Nous utilisions Firebase Hosting pour héberger notre code, et Firebase active la compression gzip par défaut. Ainsi, en hébergeant notre code sur un CDN raisonnable, nous avons pu en bénéficier sans frais.
Bien que gzip soit une méthode de compression très populaire, d'autres mécanismes tels que Zopfli et Brotli gagnent également en popularité. Brotli est compatible avec la plupart des navigateurs, et vous pouvez utiliser un binaire pour précompresser vos éléments avant de les envoyer au serveur.
Utiliser des règles de cache efficaces
L'étape suivante consistait à s'assurer que nous n'envoyions pas deux fois les ressources si ce n'était pas nécessaire.
L'audit Règle de cache inefficace de Lighthouse nous a permis de constater que nous pouvions optimiser nos stratégies de mise en cache pour atteindre exactement 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 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 une revalidation efficace des 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, du code inutilisé.
Il nous arrive d'inclure 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, 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. Au fil du temps, nous avons adopté 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 permis de le retrouver dans notre bundle.
Vous pouvez consulter les statistiques de couverture de code dans DevTools, à la fois pour l'exécution et 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 n'était pas utilisé, ainsi qu'une grande partie du code JavaScript.
Lighthouse a également détecté ce problème lors de l'audit des règles CSS inutilisées. Il a indiqué une économie potentielle de plus de 400 ko. Nous sommes donc revenus à notre code et avons supprimé les parties JavaScript et CSS de cette bibliothèque.
Cela a permis de réduire la taille de notre bundle CSS d'un facteur 20, ce qui est plutôt pas mal pour un commit de deux lignes.
Bien sûr, notre score de performances a augmenté, et le Time to Interactive s'est également amélioré.
Toutefois, avec des changements de ce type, 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 faire attention aux régressions potentielles.
Notre code n'était pas utilisé dans 95 % des cas, mais il reste encore 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. Comme il était très petit, nous avons pu réintégrer manuellement ces styles dans les boutons.
Si vous supprimez du code, assurez-vous de disposer d'un workflow de test approprié pour vous protéger contre d'éventuelles régressions visuelles.
Éviter les charges utiles réseau volumineuses
Nous savons que les ressources volumineuses peuvent ralentir le chargement des pages Web. Ils 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 certaines de nos charges utiles réseau à l'aide de l'audit Charge utile réseau énorme.
Ici, nous avons constaté que plus de 3 Mo de code étaient envoyés, ce qui est considérable, en particulier sur mobile.
Tout en haut de cette liste, Lighthouse a mis en évidence un bundle de fournisseurs JavaScript contenant 2 Mo de code non compressé. C'est également un problème mis en évidence par webpack.
Comme le dit le dicton, la requête la plus rapide est celle qui n'est pas effectuée.
Idéalement, vous devriez mesurer la valeur de chaque élément que vous diffusez auprès de 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 ressources peuvent parfois être différées, chargées de manière différée ou traitées pendant les périodes d'inactivité.
Dans notre cas, comme nous traitons de nombreux bundles JavaScript, nous avons eu la chance de pouvoir compter sur la communauté JavaScript, qui dispose d'un ensemble complet d'outils d'audit de 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 code JavaScript analysé, ce qui est assez important.
Nous avons ensuite accédé à notre éditeur et, à l'aide du plug-in Import Cost pour Visual Studio 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 l'estimation de sa taille minimisée et compressée au format Gzip. Nous avons trouvé une bonne alternative au module slug que nous utilisions, qui ne pesait que 2,2 ko.Nous l'avons donc remplacé.
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 en valait vraiment la peine.
En général, essayez donc 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 énorme différence. Veillez donc à 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 charges utiles réseau volumineuses puissent avoir un impact important sur notre application, un autre élément peut avoir un impact considérable : JavaScript.
Le JavaScript est votre ressource la plus coûteuse. Sur mobile, si vous envoyez des bundles JavaScript volumineux, cela peut retarder le moment où vos utilisateurs peuvent interagir avec les composants de votre interface utilisateur. Cela signifie qu'ils peuvent appuyer sur l'interface utilisateur sans qu'aucune action significative ne se produise. Il est donc important de comprendre pourquoi JavaScript est si coûteux.
Voici comment un navigateur traite le code 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 portable, voire un téléphone haut de gamme. Mais 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 d'essayer de réduire ce temps.
Pour vous aider à détecter ces problèmes dans votre application, nous avons ajouté un nouvel audit du temps de démarrage JavaScript à Lighthouse.
Dans le cas de l'application Oodle, nous avons constaté que le démarrage de JavaScript prenait 1,8 seconde. En fait, nous importions de manière statique toutes nos routes et tous nos composants dans un seul bundle JavaScript monolithique.
Une technique pour contourner ce problème consiste à utiliser la division du code.
La division du code consiste à ne pas donner à vos utilisateurs une pizza entière de JavaScript, mais plutôt une part à la fois, selon leurs besoins.
La division 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 plusieurs 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 a permis de charger le code de manière asynchrone et différée en fonction de nos besoins.
Cela a permis de réduire la taille de nos bundles, mais aussi de diminuer le temps de démarrage de JavaScript. Il est 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 de code JavaScript, veillez à n'envoyer à l'utilisateur que le code dont il a besoin.
Tirez parti de concepts tels que la division du code, explorez des idées comme le tree shaking et consultez le dépôt webpack-libs-optimizations pour découvrir comment réduire la taille de votre bibliothèque si vous utilisez webpack.
Optimiser les images
Dans l'application Oodle, nous utilisons beaucoup d'images. Malheureusement, Lighthouse était 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 également tirer profit de l'utilisation d'autres formats d'image.
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 des images à votre processus de compilation, avec des bibliothèques telles que imagemin.
Vous vous assurez ainsi que les images ajoutées à l'avenir seront optimisées automatiquement. Certains CDN, par exemple 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 du coût ou de problèmes de latence, des projets tels que Thumbor ou Imageflow proposent des alternatives auto-hébergées.
Notre PNG d'arrière-plan a été signalé comme volumineux dans webpack, et à juste titre. Après l'avoir redimensionné correctement pour la fenêtre d'affichage et l'avoir traité avec 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 la taille globale de la page.
Utiliser le bon format pour les contenus animés
Les GIF peuvent être très coûteux. Étonnamment, le format GIF n'a jamais été conçu comme une plate-forme d'animation à l'origine. Par conséquent, passer à un format vidéo plus adapté vous permet de réduire considérablement la taille des fichiers.
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 lourd 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 meilleure compatibilité avec les navigateurs.
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 à réduire notre poids total de plus de 80 %. Nous avons ainsi pu réduire la taille à environ 1 Mo.
Toutefois, 1 Mo est une ressource volumineuse à envoyer, en particulier pour un utilisateur disposant d'une bande passante limitée. Heureusement, nous avons pu utiliser l'API Effective Type pour détecter qu'ils disposaient d'une bande passante lente et leur fournir un JPEG beaucoup plus petit.
Cette interface utilise les valeurs effectives de délai aller-retour et de téléchargement pour estimer le type de réseau utilisé par l'utilisateur. Elle renvoie simplement une chaîne : "slow 2G", "2G", "3G" ou "4G". En fonction de cette valeur, si l'utilisateur est sur une connexion inférieure à la 4G, nous pouvons remplacer l'élément vidéo par l'image.
if (navigator.connection.effectiveType) { ... }
Cela nuit un peu à l'expérience, mais au moins, le site est utilisable sur une connexion lente.
Différer le chargement 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, et vous pourrez également le constater 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, cela signifie que vous pourriez envisager de les charger en différé.
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 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 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 à diffuser rapidement les ressources critiques
Tous les octets envoyés au navigateur n'ont pas le même degré d'importance, et le navigateur le sait. De nombreux navigateurs utilisent des heuristiques pour décider de ce qu'ils doivent récupérer en premier. Parfois, ils récupèrent donc le CSS avant les images ou les scripts.
En tant qu'auteurs de la page, il peut être utile d'indiquer au navigateur 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 indications de ressources telles que 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 basées sur la logique de chargement personnalisé, qui utilisent un script.
Voyons comment Lighthouse nous guide pour utiliser efficacement certaines de ces fonctionnalités.
La première chose que Lighthouse nous dit de faire est d'éviter les allers-retours coûteux vers une 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 à deux sous-domaines. Lighthouse nous indique que si nous pouvions préchauffer cette connexion, nous pourrions gagner jusqu'à 300 millisecondes sur le temps de connexion initial.
En utilisant l'attribut rel="preconnect" de l'élément link, nous pouvons masquer efficacement cette latence de connexion.
Cela peut avoir un impact très important, en particulier avec un service comme Google Fonts, où notre CSS de police est hébergé sur googleapis.com et nos ressources de police sont hébergées 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.
<link rel=preload> est très puissant. Il informe le navigateur qu'une ressource est nécessaire pour la navigation en cours et tente de la récupérer dès que possible.
Ici, Lighthouse nous indique que nous devrions précharger nos ressources de polices Web clés, 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, par exemple woff2.
L'impact sur votre page peut être considérable.
Normalement, sans utiliser link rel preload, si les polices Web sont essentielles à votre page, le navigateur doit d'abord récupérer votre code HTML, analyser votre code CSS et, bien plus tard, récupérer vos polices Web.
En utilisant link rel preload, 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, cela nous a permis de réduire d'une seconde le temps nécessaire pour afficher du texte à l'aide de nos polices Web.
Toutefois, ce n'est pas aussi simple si vous essayez de précharger des polices à l'aide de Google Fonts. Il y a un piège.
Les URL Google Fonts que nous spécifions sur nos polices 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'auto-héberger vos polices Web. Cela peut être très utile, car cela vous donne accès à des éléments tels que la précharge de rel de lien.
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 ou du code JavaScript comme ressources critiques, essayez d'aider le navigateur à les afficher le plus rapidement possible.
Expérimental : indices de priorité
Nous avons une surprise pour vous 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 de navigateur que nous appelons "indications de priorité".
Cette nouvelle fonctionnalité vous permet d'indiquer au navigateur l'importance d'une ressource. Elle expose un nouvel attribut, "importance", avec les valeurs "low", "high" ou "auto".
Cela nous permet de réduire 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 augmenter la priorité des éléments plus importants, comme nos images héros.
Dans le cas de notre application Oodle, cela nous a permis d'identifier un endroit où nous pouvions optimiser les performances.
Avant d'ajouter le chargement différé à nos images, le navigateur récupérait toutes les images du carrousel de doodles dès le début, 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 d'arrière-plan sur "Très faible" et celle des images de premier plan sur "Très élevée". Cela a permis de réduire de deux secondes le temps nécessaire pour récupérer et afficher ces images sur une connexion 3G lente. Une expérience positive, donc.
Nous espérons proposer cette fonctionnalité dans Canary dans quelques semaines. Restez à l'écoute !
Adopter une stratégie de chargement des polices Web
La typographie est essentielle pour une bonne conception. Si vous utilisez des polices Web, vous ne voulez idéalement pas bloquer l'affichage de votre texte, et vous ne voulez certainement pas afficher de texte invisible.
Nous mettons désormais en évidence ce problème dans Lighthouse, avec l'audit Éviter le texte invisible pendant le chargement des polices Web.
Si vous chargez vos polices Web à l'aide d'un bloc font-face, vous laissez le navigateur décider de ce qu'il doit faire si le chargement de cette police Web prend beaucoup de temps. Certains navigateurs attendent jusqu'à trois secondes avant de revenir à une police système, puis de la remplacer 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 contrôler ce processus de manière beaucoup plus précise.
@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 comment les polices Web s'afficheront ou seront remplacées en fonction du temps nécessaire pour les échanger.
Dans ce cas, nous utilisons la propriété CSS "font-display: swap". "swap" donne à la police une période de blocage de zéro seconde et une période d'échange infinie. Cela signifie que le navigateur va afficher votre texte presque immédiatement avec une police de remplacement si la police met du temps à se charger. et l'échange une fois que la police est disponible.
Dans le cas de notre application, cela nous a permis d'afficher un texte pertinent très tôt, puis de passer à la police Web une fois qu'elle était prête.
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, mais consultez également le dépôt Web Font Recipes de Zach Leatherman, car il est vraiment très utile.
Réduire les scripts bloquant l'affichage
Nous pourrions placer d'autres parties de notre application 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 chronologique de Lighthouse, vous pouvez voir que pendant les premières secondes, lorsque toutes les ressources sont en cours de chargement, l'utilisateur ne peut pas vraiment voir de contenu.
Le téléchargement et le traitement des feuilles de style externes empêchent le 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 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 index.html lors d'une étape de compilation.
Bien que ce module ait fait le plus gros du travail pour nous, il a tout de même été un peu difficile de le faire fonctionner correctement sur différentes routes.
Si vous ne 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'avez pas prévu d'architecture du 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 votre application en tenant compte des performances dès le départ, vous risquez de rencontrer des problèmes par la suite.
Au final, notre prise de 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 First Meaningful Paint.
Le résultat
Nous avons appliqué une longue liste d'optimisations des performances à notre site. Voyons le résultat. Voici comment notre application s'est chargée sur un appareil mobile moyen 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 amélioration en termes de vitesse. Toutes les modifications ont été apportées en vérifiant et en suivant en permanence le rapport Lighthouse. Si vous souhaitez découvrir comment nous avons implémenté toutes les améliorations d'un point de vue technique, n'hésitez pas à consulter notre dépôt, en particulier les demandes d'extraction 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é passionnante pour l'avenir dans de nombreux domaines. Nous espérons que l'idée selon laquelle les données réelles peuvent vraiment guider les expériences utilisateur que nous créons encouragera d'autres expérimentations à l'avenir.
Aujourd'hui, nous prenons de nombreuses décisions arbitraires sur ce que l'utilisateur peut vouloir ou avoir besoin, et donc sur ce qui mérite d'être préchargé ou mis en cache préalable. Si nous devinons correctement, nous pouvons prioriser un petit nombre de ressources, mais il est très difficile d'étendre cette approche à l'ensemble du site Web.
Nous disposons désormais de données pour mieux orienter nos optimisations. En utilisant l'API Google Analytics Reporting, nous pouvons examiner la page suivante la plus consultée 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 avec un bon modèle de probabilité, nous évitons de gaspiller les données de l'utilisateur en préchargeant de manière agressive trop de 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 implémenter ces modèles.
Pour faciliter ces tests, nous sommes heureux d'annoncer une nouvelle initiative que nous appelons 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 que cela vous incitera à explorer l'utilisation des données pour améliorer les performances Web et aller au-delà. Tout est Open Source et disponible sur GitHub dès aujourd'hui. 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 que des moyens, pas des objectifs en soi.
Nous avons tous déjà été confrontés à des chargements de page 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 continu. De nombreux petits changements peuvent entraîner des gains importants. En utilisant les bons outils d'optimisation et en gardant un œil sur les rapports Lighthouse, vous pouvez offrir une expérience plus inclusive et de meilleure qualité à vos utilisateurs.
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 Google Doodles.