Software Engineering18 juillet 20268 min read

Comment nous construisons des sites web rapides : un guide de terrain des Core Web Vitals

Les Core Web Vitals ne sont pas un tableau de scores, ce sont une promesse faite à vos utilisateurs. Voici exactement comment nous construisons des sites web rapides chez Innovation T, de la stratégie d'images à l'activation conditionnelle du WebGL sur les appareils capables.

Par Innovation T Team


Un site web lent perd les gens avant même d'avoir eu la chance de plaider sa cause. Quelqu'un appuie sur votre lien depuis un téléphone Android de milieu de gamme sur une connexion instable, attend, voit la mise en page sauter dans tous les sens, appuie sur un bouton qui ne fait rien pendant une demi-seconde, puis s'en va. Aucun texte astucieux ne survit à cette expérience. Chez Innovation T, nous traitons la performance comme une fonctionnalité du produit, et non comme une tâche de nettoyage, et les Core Web Vitals sont le langage que Google nous donne pour la mesurer.

Voici le guide de terrain que nous utilisons réellement lorsque nous construisons. Il explique ce que signifient les métriques en termes simples, puis vous donne les tactiques concrètes vers lesquelles nous nous tournons sur de vrais projets.

Ce que les métriques mesurent réellement

Les Core Web Vitals sont trois métriques centrées sur l'utilisateur, plus une métrique de laboratoire qui vous aide à trouver les problèmes avant vos utilisateurs. Oubliez les acronymes un instant et pensez à ce que ressent l'utilisateur.

LCP (Largest Contentful Paint) répond à une question simple : combien de temps avant que l'élément principal de cette page n'apparaisse ? Cet "élément principal" est généralement une image de héros, un titre ou un grand bloc de texte. Si votre LCP est de 4 secondes, votre visiteur fixe un écran presque vide pendant 4 secondes. Google considère que 2,5 secondes ou moins est un bon résultat.

INP (Interaction to Next Paint) mesure la réactivité. Lorsque quelqu'un appuie, clique ou tape, combien de temps avant que la page ne réagisse visiblement ? INP a remplacé l'ancienne métrique First Input Delay parce qu'elle examine toutes les interactions au cours de la visite, et pas seulement la première. Un bouton lent, un menu qui s'ouvre avec un temps de retard, un champ de formulaire qui saccade : voilà un mauvais INP. Un bon résultat est de 200 millisecondes ou moins.

CLS (Cumulative Layout Shift) mesure la stabilité visuelle. C'est la frustration de lire un paragraphe et de le voir sauter parce qu'une image ou une publicité s'est chargée au-dessus, ou de tendre le doigt vers un bouton qui glisse soudainement de sous votre doigt. Un bon CLS est de 0,1 ou moins.

TBT (Total Blocking Time) est l'équivalent en laboratoire de l'INP. Il mesure combien de temps le thread principal a été bloqué et incapable de répondre pendant le chargement de la page. Vous verrez le TBT dans Lighthouse et d'autres outils de laboratoire. Un TBT élevé prédit presque toujours un mauvais INP sur le terrain, nous l'utilisons donc comme signal d'alerte précoce pendant le développement.

Le schéma ici est important. Le LCP concerne le chargement, l'INP et le TBT concernent l'interactivité, et le CLS concerne la stabilité. La plupart du travail de performance se résume à envoyer moins de choses au navigateur et à faire moins de travail sur le thread principal. Tout ce qui suit est une variante de ces deux idées.

Stratégie d'images : généralement le plus grand gain

Les images sont l'élément le plus lourd sur la plupart des pages, et l'image de héros est fréquemment l'élément LCP, c'est donc par là que nous commençons.

  • Servez des formats modernes. AVIF et WebP sont considérablement plus légers que JPEG ou PNG à qualité égale. Nous servons de l'AVIF avec une solution de repli en WebP et ne recourons aux formats plus anciens que lorsque nous y sommes vraiment obligés.
  • Dimensionnez les images à leur taille d'affichage et livrez des variantes responsives. Utilisez srcset et sizes pour qu'un téléphone télécharge une image à sa taille, et non une ressource de bureau de 2000 pixels réduite dans le navigateur.
  • Définissez toujours une width et une height explicites (ou une aspect-ratio en CSS). Cela réserve l'espace avant le chargement de l'image et constitue le correctif unique le plus efficace pour le CLS.
  • Priorisez l'image LCP et chargez le reste en différé. Ajoutez fetchpriority="high" au héros et loading="lazy" à tout ce qui se trouve sous la ligne de flottaison afin que les images hors écran ne se disputent pas la bande passante pendant le premier rendu critique.
  • Envisagez un indice de préchargement (preload) pour l'image de héros afin que le navigateur commence à la récupérer avant d'avoir fini d'analyser le CSS.

Réussir l'image de héros suffit souvent à faire passer le LCP sous la barre des 2,5 secondes à lui seul. La même discipline s'applique à la vidéo : utilisez une image d'affiche (poster), et ne lancez jamais en lecture automatique une vidéo d'arrière-plan lourde sur mobile.

Chargement des polices : arrêtez le texte invisible

Les polices web sont un tueur silencieux de LCP et de CLS. Une page attend une police personnalisée, n'affiche rien (ou affiche un texte de repli qui se recompose ensuite), et l'utilisateur en paie le prix.

  • Ajoutez font-display: swap afin que le texte s'affiche immédiatement dans une police de repli et bascule vers la police web à son arrivée. Les utilisateurs peuvent lire pendant que la police se charge.
  • Hébergez vos polices vous-même au lieu de les récupérer auprès d'un tiers. Cela supprime une connexion supplémentaire et vous donne le contrôle du cache.
  • Préchargez le ou les deux fichiers de police critiques pour qu'ils commencent à se télécharger tôt.
  • Réduisez les polices (subsetting) aux caractères et aux graisses que vous utilisez réellement. Livrer toutes les graisses d'une famille alors que vous en utilisez deux est du pur gaspillage.
  • Choisissez une police de repli aux métriques similaires, ou ajustez-la avec size-adjust, afin que le basculement ne provoque pas de recomposition visible. Cela protège le CLS.

Réduire le JavaScript du thread principal

Le JavaScript est l'endroit où un bon INP et un bon TBT vont mourir. Chaque script que le navigateur doit analyser, compiler et exécuter monopolise le thread principal, et tant que ce thread est occupé, il ne peut pas répondre aux interactions tactiles. C'est le domaine le plus difficile et le plus précieux à maîtriser.

  • Envoyez moins. Auditez votre bundle et supprimez les dépendances dont vous n'avez pas besoin. Une bibliothèque de dates, un énorme kit d'interface utilisé pour un seul composant, trois bibliothèques utilitaires qui se chevauchent : cela s'accumule vite.
  • Fractionnez le code (code splitting) et chargez en différé. Chargez le JavaScript d'une route ou d'un composant uniquement lorsque c'est nécessaire, et non tout d'un coup au départ. Une fenêtre modale qui s'ouvre au clic n'a pas besoin de figurer dans le bundle initial.
  • Différez les scripts non critiques. Les outils d'analyse, les widgets de chat et les balises marketing devraient se charger après que la page est interactive, et non entrer en concurrence avec elle. Utilisez defer ou chargez-les à l'inactivité (on idle).
  • Découpez les tâches longues. Toute tâche de plus de 50 millisecondes bloque l'interaction. Fractionnez le travail lourd et rendez la main au thread principal afin que le navigateur puisse répondre aux entrées entre les fragments.
  • Privilégiez la plateforme. Une grande partie de ce pour quoi les gens installent des bibliothèques (validation de formulaire, animation simple, formatage de dates) est désormais gérée nativement par le navigateur. Nous construisons des pages à forte conversion avec moins de code, un thème que nous abordons dans notre guide sur l'anatomie d'une landing page à forte conversion.

Activation conditionnelle des bibliothèques WebGL et d'animation lourdes

C'est ici que l'expérience de terrain sépare les bons sites des sites saccadés. Des visuels riches, des scènes WebGL et des animations basées sur la physique sont superbes sur un ordinateur portable haut de gamme et transforment un téléphone d'entrée de gamme en diaporama. La solution n'est pas de les supprimer, mais de les servir de manière conditionnelle.

  • N'exécutez du WebGL lourd que lorsqu'un vrai GPU est présent. Avant de monter une scène 3D coûteuse, nous détectons le contexte de rendu et vérifions le moteur de rendu signalé. Sur un moteur de rendu logiciel ou un appareil qui échoue à un test rapide de capacité, nous nous rabattons sur une image statique ou une version CSS légère au lieu d'une boucle WebGL complète.
  • Respectez l'utilisateur. Honorez la requête média prefers-reduced-motion et sautez les animations non essentielles pour les personnes qui le demandent. Sautez également les effets lourds lorsque l'appareil signale peu de cœurs CPU ou que l'indice Save Data est activé.
  • Déplacez l'animation vers le CSS partout où vous le pouvez. Les animations de transformation et d'opacité en CSS s'exécutent sur le thread de composition et sont peu coûteuses. Un effet au survol, un fondu, un glissement subtil : cela relève du CSS, et non d'une bibliothèque d'animation JavaScript qui s'exécute sur le thread principal.
  • Limitez votre boucle de rendu. Si vous devez exécuter une boucle de trames d'animation, plafonnez la fréquence d'images, et mettez-la entièrement en pause lorsque l'élément sort du champ de vision par défilement ou que l'onglet est masqué. Une boucle qui repeint à pleine vitesse pour un canvas hors écran est du pur gaspillage qui se traduit par un mauvais INP.
  • Ne chargez la bibliothèque lourde que lorsque l'effet est réellement visible. Utilisez un intersection observer pour que le bundle WebGL ou d'animation se télécharge quand l'utilisateur défile près de lui, et non au chargement initial.

Chargement différé, mise en cache et CDN

La dernière couche consiste à ne pas faire le travail deux fois et à ne pas servir depuis un endroit lointain.

  • Chargez en différé le contenu sous la ligne de flottaison : images, iframes, intégrations et composants lourds. Le navigateur dispose du loading="lazy" natif pour les images et les iframes, et un intersection observer couvre tout le reste.
  • Mettez en cache agressivement. Les ressources statiques dont le nom de fichier contient un hachage de contenu peuvent être mises en cache pendant un an, car une modification du fichier change le nom du fichier. Définissez des en-têtes Cache-Control longs pour celles-ci et plus courts pour le HTML.
  • Utilisez un CDN. Servir les ressources depuis un emplacement en périphérie (edge) proche de votre utilisateur réduit directement la latence, ce qui aide le LCP. Un CDN absorbe également les pics de trafic et allège la charge sur votre serveur d'origine.
  • Compressez tout. Brotli pour les ressources textuelles surpasse gzip, et devrait être activé par défaut au niveau du serveur ou du CDN.
  • Réduisez le temps de réponse du serveur. Un premier octet lent empoisonne toutes les métriques en aval. Mettez en cache les pages rendues lorsque vous le pouvez, et gardez le travail de base de données hors du chemin critique. Lorsque nous concevons les API derrière ces pages, nous optimisons exactement pour cela, un sujet que nous approfondissons dans concevoir des API que les développeurs adorent.

La checklist de performance

Voici la liste numérotée que nous parcourons avant de livrer.

  1. Confirmez l'élément LCP (généralement l'image de héros ou le titre) et donnez-lui un chargement prioritaire.
  2. Servez de l'AVIF ou du WebP, dimensionné de façon responsive avec srcset et sizes.
  3. Définissez des dimensions explicites ou une aspect-ratio sur chaque image et intégration média pour éliminer les décalages de mise en page.
  4. Chargez en différé chaque image, iframe et composant lourd sous la ligne de flottaison.
  5. Hébergez vous-même les polices, réduisez-les (subset), préchargez les fichiers critiques et utilisez font-display: swap.
  6. Auditez le bundle JavaScript et supprimez ou remplacez les dépendances lourdes.
  7. Fractionnez le code par route et chargez en différé les composants qui ne sont pas nécessaires au premier rendu.
  8. Différez les scripts d'analyse, de chat et de marketing jusqu'à ce que la page soit interactive.
  9. Découpez toute tâche du thread principal plus longue que 50 millisecondes et rendez la main entre les fragments.
  10. Activez le WebGL uniquement après une vérification de vrai GPU, avec une solution de repli statique pour les appareils faibles.
  11. Déplacez les animations vers les transformations et l'opacité en CSS, et honorez prefers-reduced-motion.
  12. Limitez et mettez en pause les boucles de rendu lorsqu'elles sont hors écran ou que l'onglet est masqué.
  13. Définissez des en-têtes de cache longs sur les ressources statiques hachées et plus courts sur le HTML.
  14. Servez via un CDN avec la compression Brotli activée.
  15. Mesurez avec des outils de laboratoire (Lighthouse, TBT) pendant le développement, puis validez avec des données de terrain (LCP, INP, CLS réels) après la mise en ligne.

Ce dernier point est celui que les gens sautent. Les scores de laboratoire vous indiquent où sont les problèmes, mais seules les données de terrain vous disent ce que vos vrais utilisateurs vivent sur leurs vrais appareils et réseaux. Nous construisons pour le laboratoire et vérifions sur le terrain.

La rapidité est une décision de conception que vous prenez délibérément, encore et encore, à chaque couche. Faites-le bien et les métriques se règlent d'elles-mêmes, car elles ne sont que la mesure d'un site qui respecte la personne qui l'utilise.

Si votre site vous semble lent et que vous ne savez pas où passe le temps, c'est exactement le genre de problème que nous aimons. Jetez un œil à nos services ou contactez-nous et nous vous aiderons à construire quelque chose de rapide.

#Core Web Vitals#performance web#LCP#INP

Prêt à construire avec Innovation T ?

Qu'il s'agisse de sécurité, de croissance ou d'ingénierie, notre équipe peut vous aider à livrer dans les meilleures conditions.