Comment nous avons amélioré nos principaux éléments vitaux Web (étude de cas)

Publié: 2022-03-10
Résumé rapide ↬ La "Page Experience Update" de Google commencera à être déployée en juin. Dans un premier temps, les sites qui respectent les seuils Core Web Vitals auront un avantage de classement mineur dans la recherche mobile pour tous les navigateurs. La recherche est importante pour toute entreprise, et c'est l'histoire de la façon dont Beau Hartshorne et son équipe chez Instant Domain Search ont amélioré leurs scores Core Web Vitals. De plus, un outil open source qu'ils ont construit en cours de route.

L'année dernière, Google a commencé à souligner l'importance de Core Web Vitals et comment ils reflètent l'expérience réelle d'une personne lors de la visite de sites sur le Web. La performance est une caractéristique essentielle de notre entreprise, Instant Domain Search, c'est dans le nom. Imaginez notre surprise lorsque nous avons constaté que nos scores vitaux n'étaient pas bons pour beaucoup de gens. Nos ordinateurs rapides et notre Internet par fibre ont masqué l'expérience que les vraies personnes ont sur notre site. Il n'a pas fallu longtemps avant qu'une mer d'avis rouges « médiocre » et jaunes « nécessite une amélioration » dans notre console de recherche Google requière notre attention. L'entropie avait gagné, et nous devions trouver un moyen de nettoyer le bric-à-brac et de rendre notre site plus rapide.

Une capture d'écran de Google Search Console montrant que nous devons améliorer nos métriques Core Web Vitals
Ceci est une capture d'écran de notre rapport Mobile Core Web Vitals dans Google Search Console. Nous avons encore beaucoup de travail à faire ! ( Grand aperçu )

J'ai fondé Instant Domain Search en 2005 et l'ai gardé comme activité secondaire pendant que je travaillais pour une société Y Combinator (Snipshot, W06), avant de travailler comme ingénieur logiciel chez Facebook. Nous sommes récemment devenus un petit groupe basé principalement à Victoria, au Canada, et nous travaillons sur un long carnet de commandes de nouvelles fonctionnalités et d'améliorations des performances. Nos faibles scores Web Vitals et la mise à jour imminente de Google ont concentré notre attention sur la recherche et la résolution de ces problèmes.

Lorsque la première version du site a été lancée, je l'avais construit avec PHP, MySQL et XMLHttpRequest. Internet Explorer 6 était entièrement pris en charge, Firefox gagnait en parts de marché et Chrome était encore à des années du lancement. Au fil du temps, nous avons évolué à travers une variété de générateurs de sites statiques, de frameworks JavaScript et de technologies de serveur. Notre pile frontale actuelle est React servie avec Next.js et un service backend intégré Rust pour répondre à nos recherches de noms de domaine. Nous essayons de suivre les meilleures pratiques en servant autant que possible sur un CDN, en évitant autant de scripts tiers que possible et en utilisant de simples graphiques SVG au lieu de PNG bitmap. Ce n'était pas assez.

Next.js nous permet de construire nos pages et composants en React et TypeScript. Lorsqu'il est associé à VS Code, l'expérience de développement est incroyable. Next.js fonctionne généralement en transformant les composants React en HTML et CSS statiques. De cette façon, le contenu initial peut être servi à partir d'un CDN, puis Next peut « hydrater » la page pour rendre les éléments dynamiques. Une fois la page hydratée, notre site se transforme en une application d'une seule page où les gens peuvent rechercher et générer des noms de domaine. Nous ne comptons pas sur Next.js pour faire beaucoup de travail côté serveur, la majorité de notre contenu est exportée de manière statique au format HTML, CSS et JavaScript pour être servie à partir d'un CDN.

Plus après saut! Continuez à lire ci-dessous ↓

Lorsqu'une personne commence à rechercher un nom de domaine, nous remplaçons le contenu de la page par les résultats de la recherche. Pour rendre les recherches aussi rapides que possible, le front-end interroge directement notre backend Rust qui est fortement optimisé pour les recherches et les suggestions de domaine. De nombreuses requêtes auxquelles nous pouvons répondre instantanément, mais pour certains TLD, nous devons effectuer des requêtes DNS plus lentes qui peuvent prendre une seconde ou deux à résoudre. Lorsque certaines de ces requêtes plus lentes seront résolues, nous mettrons à jour l'interface utilisateur avec toutes les nouvelles informations qui arriveront. Les pages de résultats sont différentes pour tout le monde, et il peut être difficile pour nous de prédire exactement comment chaque personne vit le site.

Les Chrome DevTools sont excellents et constituent un bon point de départ pour rechercher des problèmes de performances. La vue Performances montre exactement quand les requêtes HTTP sortent, où le navigateur passe du temps à évaluer JavaScript, et plus :

Capture d'écran du volet Performances dans Chrome DevTools
Capture d'écran du volet Performances dans Chrome DevTools. Nous avons activé Web Vitals qui nous permet de voir quel élément a causé le LCP. ( Grand aperçu )

Il existe trois métriques Core Web Vitals que Google utilisera pour aider à classer les sites dans sa prochaine mise à jour de l'algorithme de recherche. Google regroupe les expériences en "bonnes", "nécessite une amélioration" et "mauvaises" en fonction des scores LCP, FID et CLS que de vraies personnes ont sur le site :

  • LCP , ou Largest Contentful Paint, définit le temps nécessaire pour que le plus grand élément de contenu devienne visible.
  • FID , ou First Input Delay, se rapporte à la réactivité d'un site à l'interaction, c'est-à-dire le temps entre un appui, un clic ou une pression sur une touche dans l'interface et la réponse de la page.
  • CLS , ou Cumulative Layout Shift, suit la façon dont les éléments se déplacent ou se déplacent sur la page en l'absence d'actions telles qu'un événement de clavier ou de clic.
Graphiques montrant les plages de scores LCP, FID et CLS acceptables
Un résumé de LCP, FID et CLS. (Crédit image: Web Vitals par Philip Walton) ( Grand aperçu )

Chrome est configuré pour suivre ces statistiques sur tous les utilisateurs de Chrome connectés et envoie des statistiques anonymes résumant l'expérience d'un client sur un site à Google pour évaluation. Ces scores sont accessibles via le rapport d'expérience utilisateur Chrome et sont affichés lorsque vous inspectez une URL avec l'outil PageSpeed ​​Insights. Les scores représentent l'expérience du 75e centile pour les personnes ayant visité cette URL au cours des 28 jours précédents. C'est le nombre qu'ils utiliseront pour aider à classer les sites dans la mise à jour.

Une métrique du 75e centile (p75) établit un équilibre raisonnable pour les objectifs de performance. Prendre une moyenne, par exemple, cacherait beaucoup de mauvaises expériences que les gens ont. La médiane, ou 50e centile (p50), signifierait que la moitié des personnes utilisant notre produit avaient une expérience pire. Le 95e centile (p95), en revanche, est difficile à construire car il capture trop de valeurs aberrantes extrêmes sur les anciens appareils avec des connexions inégales. Nous estimons que la notation basée sur le 75e centile est une norme équitable à respecter.

Graphique illustrant une distribution des valeurs p50 et p75
La médiane, également connue sous le nom de 50e centile ou p50, est indiquée en vert. Le 75e centile, ou p75, est représenté ici en jaune. Dans cette illustration, nous montrons 20 séances. La 15e pire session est le 75e centile et ce que Google utilisera pour évaluer l'expérience de ce site. ( Grand aperçu )

Pour maîtriser nos scores, nous nous sommes d'abord tournés vers Lighthouse pour obtenir d'excellents outils intégrés à Chrome et hébergés sur web.dev/measure/ et sur PageSpeed ​​Insights. Ces outils nous ont aidés à trouver quelques problèmes techniques généraux avec notre site. Nous avons vu que la façon dont Next.js regroupait notre CSS et ralentissait notre temps de rendu initial, ce qui affectait notre FID. La première victoire facile est venue d'une fonctionnalité expérimentale de Next.js, OptimizeCss, qui a permis d'améliorer considérablement notre score de performance général.

Lighthouse a également détecté une mauvaise configuration du cache qui a empêché certains de nos actifs statiques d'être servis à partir de notre CDN. Nous sommes hébergés sur Google Cloud Platform, et le Google Cloud CDN exige que l'en-tête Cache-Control contienne « public ». Next.js ne vous permet pas de configurer tous les en-têtes qu'il émet, nous avons donc dû les remplacer en plaçant le serveur Next.js derrière Caddy, un serveur proxy HTTP léger implémenté dans Go. Nous en avons également profité pour nous assurer que nous servions ce que nous pouvions avec la prise en charge relativement nouvelle de l'obsolescence pendant la revalidation dans les navigateurs modernes, qui permet au CDN de récupérer le contenu de l'origine (notre serveur Next.js) de manière asynchrone en arrière-plan.

Il est facile, peut-être trop facile, d'ajouter presque tout ce dont vous avez besoin à votre produit à partir de npm. Il ne faut pas longtemps pour que la taille des bundles augmente. Les gros bundles prennent plus de temps à télécharger sur les réseaux lents, et le téléphone mobile du 75e centile passera beaucoup de temps à bloquer le thread principal de l'interface utilisateur pendant qu'il essaie de donner un sens à tout le code qu'il vient de télécharger. Nous avons aimé BundlePhobia qui est un outil gratuit qui montre combien de dépendances et d'octets un paquet npm ajoutera à votre bundle. Cela nous a conduit à éliminer ou à remplacer un certain nombre d'animations alimentées par des ressorts réactifs par des transitions CSS plus simples :

Capture d'écran de l'outil BundlePhobia montrant que react-spring ajoute 162,8 Ko de JavaScript
Nous avons utilisé BundlePhobia pour nous aider à détecter les grandes dépendances dont nous pourrions nous passer. ( Grand aperçu )

Grâce à l'utilisation de BundlePhobia et Lighthouse, nous avons constaté que les logiciels tiers de journalisation et d'analyse des erreurs contribuaient de manière significative à la taille et au temps de chargement de notre bundle. Nous avons supprimé et remplacé ces outils par notre propre journalisation côté client qui tire parti des API de navigateur modernes telles que sendBeacon et ping. Nous envoyons la journalisation et les analyses à notre propre infrastructure Google BigQuery où nous pouvons répondre aux questions qui nous intéressent plus en détail que n'importe quel outil standard pourrait fournir. Cela élimine également un certain nombre de cookies tiers et nous donne beaucoup plus de contrôle sur la manière et le moment où nous envoyons les données de journalisation des clients.

Notre score CLS avait encore la plus grande marge d'amélioration. La façon dont Google calcule le CLS est compliquée : vous disposez d'une "fenêtre de session" maximale avec un intervalle d'une seconde, plafonnée à 5 secondes à partir du chargement initial de la page, ou à partir d'une interaction au clavier ou au clic, pour terminer le déplacement des éléments sur le site. . Si vous souhaitez en savoir plus sur ce sujet, voici un excellent guide sur le sujet. Cela pénalise de nombreux types de superpositions et de popups qui apparaissent juste après avoir atterri sur un site. Par exemple, les publicités qui déplacent le contenu ou les ventes incitatives qui peuvent apparaître lorsque vous commencez à faire défiler les publicités pour atteindre le contenu. Cet article fournit une excellente explication de la façon dont le score CLS est calculé et du raisonnement qui le sous-tend.

Nous sommes fondamentalement opposés à ce genre d'encombrement numérique, nous avons donc été surpris de voir à quel point Google insistait pour que nous nous améliorions. Chrome a une superposition Web Vitals intégrée à laquelle vous pouvez accéder en utilisant le menu de commande pour "Afficher la superposition Core Web Vitals". Pour voir exactement quels éléments Chrome prend en compte dans son calcul CLS, nous avons trouvé l'option "Console Logging" de l'extension Chrome Web Vitals dans les paramètres plus utile. Une fois activé, ce plugin affiche vos scores LCP, FID et CLS pour la page en cours. Depuis la console, vous pouvez voir exactement quels éléments de la page sont connectés à ces scores. Nos scores CLS avaient le plus de marge d'amélioration.

Capture d'écran de l'affichage tête haute du plug-in Chrome Web Vitals
L'extension Chrome Web Vitals montre comment Chrome note la page actuelle sur ses métriques Web Vitals. Certaines de ces fonctionnalités seront intégrées à Chrome 90. ( Grand aperçu )

Parmi les trois métriques, CLS est la seule qui s'accumule lorsque vous interagissez avec une page. L'extension Web Vitals a une option de journalisation qui montrera exactement quels éléments provoquent le CLS lorsque vous interagissez avec un produit. Regardez comment les métriques CLS s'ajoutent lorsque nous faisons défiler la page d'accueil de Smashing Magazine :

Lorsque la journalisation est activée sur l'extension Chrome Web Vitals, les modifications de mise en page sont enregistrées dans la console lorsque vous interagissez avec un site.

Google continuera d'ajuster la façon dont il calcule le CLS au fil du temps, il est donc important de rester informé en suivant le blog de développement Web de Google. Lorsque vous utilisez des outils tels que l'extension Chrome Web Vitals, il est important d'activer la limitation du processeur et du réseau pour obtenir une expérience plus réaliste. Vous pouvez le faire avec les outils de développement en simulant un processeur mobile.

Une capture d'écran montrant comment activer la limitation du processeur dans Chrome DevTools
Il est important de simuler un processeur et une connexion réseau plus lents lorsque vous recherchez des problèmes Web Vitals sur votre site. ( Grand aperçu )

La meilleure façon de suivre la progression d'un déploiement à l'autre est de mesurer les expériences de page de la même manière que Google. Si vous avez configuré Google Analytics, un moyen simple de le faire est d'installer le module Web Vitals de Google et de le connecter à Google Analytics. Cela fournit une mesure approximative de vos progrès et les rend visibles dans un tableau de bord Google Analytics.

Un graphique montrant les scores moyens de nos valeurs CLS au fil du temps
Google Analytics peut afficher une valeur moyenne de vos scores Web Vitals. ( Grand aperçu )

C'est là que nous nous sommes heurtés à un mur. Nous pouvions voir notre score CLS, et même si nous l'avions considérablement amélioré, nous avions encore du travail à faire. Notre score CLS était d'environ 0,23 et nous devions le ramener en dessous de 0,1, et de préférence jusqu'à 0. À ce stade, cependant, nous ne pouvions pas trouver quelque chose qui nous disait exactement quels composants sur quelles pages affectaient encore le score. Nous avons pu voir que Chrome exposait beaucoup de détails dans leurs outils Core Web Vitals, mais que les agrégateurs de journalisation jetaient la partie la plus importante : quel élément de page était à l'origine du problème.

Une capture d'écran de la console Chrome DevTools montrant quels éléments provoquent le CLS.
Cela montre exactement quels éléments contribuent à votre score CLS. ( Grand aperçu )

Pour capturer tous les détails dont nous avons besoin, nous avons créé une fonction sans serveur pour capturer les données Web Vitals des navigateurs. Comme nous n'avons pas besoin d'exécuter des requêtes en temps réel sur les données, nous les diffusons dans l'API de diffusion en continu de Google BigQuery pour le stockage. Cette architecture signifie que nous pouvons capturer à peu de frais autant de points de données que nous pouvons en générer.

Après avoir appris quelques leçons en travaillant avec Web Vitals et BigQuery, nous avons décidé de regrouper cette fonctionnalité et de publier ces outils en open source sur vitals.dev.

L'utilisation d'Instant Vitals est un moyen rapide de commencer à suivre vos scores Web Vitals dans BigQuery. Voici un exemple de schéma de table BigQuery que nous créons :

Une capture d'écran de nos schémas BigQuery pour capturer FCP
L'un de nos schémas BigQuery. ( Grand aperçu )

L'intégration avec Instant Vitals est facile. Vous pouvez commencer par intégrer la bibliothèque cliente pour envoyer des données à votre fonction backend ou sans serveur :

 import { init } from "@instantdomain/vitals-client"; init({ endpoint: "/api/web-vitals" });

Ensuite, sur votre serveur, vous pouvez intégrer la bibliothèque du serveur pour compléter le circuit :

 import fs from "fs"; import { init, streamVitals } from "@instantdomain/vitals-server"; // Google libraries require service key as path to file const GOOGLE_SERVICE_KEY = process.env.GOOGLE_SERVICE_KEY; process.env.GOOGLE_APPLICATION_CREDENTIALS = "/tmp/goog_creds"; fs.writeFileSync( process.env.GOOGLE_APPLICATION_CREDENTIALS, GOOGLE_SERVICE_KEY ); const DATASET_; init({ datasetId: DATASET_ID }).then().catch(console.error); // Request handler export default async (req, res) => { const body = JSON.parse(req.body); await streamVitals(body, body.name); res.status(200).end(); };

Appelez simplement streamVitals avec le corps de la requête et le nom de la métrique pour envoyer la métrique à BigQuery. La bibliothèque se chargera de créer le jeu de données et les tables pour vous.

Après avoir collecté une journée de données, nous avons exécuté cette requête comme celle-ci :

 SELECT `<project_name>.web_vitals.CLS`.Value, Node FROM `<project_name>.web_vitals.CLS` JOIN UNNEST(Entries) AS Entry JOIN UNNEST(Entry.Sources) WHERE Node != "" ORDER BY value LIMIT 10

Cette requête produit des résultats comme celui-ci :

Évaluer Nœud
4.6045324800736724E-4 /html/body/div[1]/main/div/div/div[2]/div/div/blockquote
7.183070668914928E-4 /html/body/div[1]/header/div/div/header/div
0.031002668277977697 /html/body/div[1]/footer
0.035830703317463526 /html/body/div[1]/main/div/div/div[2]
0.035830703317463526 /html/body/div[1]/footer
0.035830703317463526 /html/body/div[1]/main/div/div/div[2]
0.035830703317463526 /html/body/div[1]/main/div/div/div[2]
0.035830703317463526 /html/body/div[1]/footer
0.035830703317463526 /html/body/div[1]/footer
0.03988482067913317 /html/body/div[1]/footer

Cela nous montre quels éléments sur quelles pages ont le plus d'impact sur CLS. Il a créé une liste de pointage que notre équipe doit étudier et corriger. Sur Instant Domain Search, il s'avère que des connexions mobiles lentes ou mauvaises prendront plus de 500 ms pour charger certains de nos résultats de recherche. L'un des pires contributeurs à CLS pour ces utilisateurs était en fait notre pied de page.

Le score de décalage de mise en page est calculé en fonction de la taille de l'élément déplacé et de sa distance. Dans notre vue des résultats de recherche, si un appareil prend plus d'un certain temps pour recevoir et afficher les résultats de la recherche, la vue des résultats se réduirait à une zero-height , ce qui afficherait le pied de page. Lorsque les résultats arrivent, ils repoussent le pied de page en bas de la page. Un gros élément DOM se déplaçant aussi loin a beaucoup ajouté à notre score CLS. Pour résoudre ce problème correctement, nous devons restructurer la manière dont les résultats de la recherche sont collectés et rendus. Nous avons décidé de supprimer simplement le pied de page dans la vue des résultats de recherche comme un hack rapide qui l'empêcherait de rebondir sur les connexions lentes.

Nous examinons maintenant régulièrement ce rapport pour suivre notre amélioration et l'utilisons pour lutter contre la baisse des résultats à mesure que nous progressons. Nous avons été témoins de la valeur d'une attention supplémentaire aux fonctionnalités et produits nouvellement lancés sur notre site et avons opérationnalisé des contrôles cohérents pour nous assurer que les éléments vitaux de base agissent en faveur de notre classement. Nous espérons qu'en partageant Instant Vitals, nous pourrons également aider d'autres développeurs à atteindre leurs scores Core Web Vitals.

Google fournit d'excellents outils de performance intégrés à Chrome, et nous les avons utilisés pour trouver et résoudre un certain nombre de problèmes de performances. Nous avons appris que les données de terrain fournies par Google offraient un bon résumé de nos progrès p75, mais n'avaient pas de détails exploitables. Nous devions savoir exactement quels éléments DOM provoquaient des changements de mise en page et des retards d'entrée. Une fois que nous avons commencé à collecter nos propres données de terrain, avec des requêtes XPath, nous avons pu identifier des opportunités spécifiques pour améliorer l'expérience de chacun sur notre site. Avec quelques efforts, nous avons ramené nos scores de champ Core Web Vitals réels dans une plage acceptable en préparation de la mise à jour de l'expérience de page de juin. Nous sommes heureux de voir ces chiffres descendre et aller à droite !

Une capture d'écran de Google PageSpeed ​​Insights montrant que nous réussissons l'évaluation Core Web Vitals
Google PageSpeed ​​Insights montre que nous réussissons maintenant l'évaluation Core Web Vitals. ( Grand aperçu )