< BACK Core Web Vitals sur les grands sites : comment atteindre un LCP inférieur à 1,5s -- illustration en trait fin

Core Web Vitals sur les grands sites : comment atteindre un LCP inférieur à 1,5s

En 2022, un site de comparaison d'hébergeurs m'est arrivé dans la boîte de réception. Grand catalogue, environ 4 000 pages, structure de catégories profondément imbriquées, des liens d'affiliation éparpillés partout, des images héros de la taille de petits continents. Leur Google Search Console était un cauchemar. LCP à 4,2 secondes sur mobile. INP (à l'époque encore appelé FID) limite. Le client avait déjà dépensé 6 000 £ avec une agence précédente qui lui avait collé un CDN et appelé ça un jour.

Ce projet est celui qui a finalement façonné notre façon de penser la performance chez Seahawk pour les sites à fort nombre de pages, les annuaires, les plateformes de listes, les propriétés d'avis d'hébergement comme les builds HostList. Ce qui suit est le playbook réel.performance at Seahawk for high-page-count sites, directory sites, listing platforms, hosting review properties like HostList-style builds. What follows is the actual playbook.

---

Pourquoi les grands sites cassent LCP différemment

Les petits sites ont des problèmes simples. Une image hero, un thème, un plugin qui en fait trop. Réparez ces trois choses et vous êtes sous 2 secondes.

Les gros sites ? C'est un animal complètement différent. L'élément LCP change selon la page où tu te trouves. Une archive de catégories a un candidat LCP différent d'une page de détail produit, qui a un candidat différent de la page d'accueil. La plupart des outils de performance rapportent un score unique. Ce chiffre est un mensonge, c'est une moyenne d'un ensemble sauvagement varié de pages, et corriger la page d'accueil en ignorant les 3 800 pages de listes en dessous, c'est exactement comment les agences se font une mauvaise réputation.which page you're on. A category archive has a different LCP candidate than a product detail page, which has a different candidate than the homepage. Most performance tools report a single score. That number is a lie, it's an average of a wildly varied set of pages, and fixing the homepage while ignoring the 3,800 listing pages underneath it is exactly how agencies earn bad reputations.

La documentation Core Web Vitals de Google est claire : les données de terrain, ce que les vrais utilisateurs vivent, mesuré dans le rapport Chrome User Experience, c'est ce que Google utilise réellement pour les signaux de classement. Les données de lab de PageSpeed Insights sont directionnelles, pas définitives. J'ai vu des sites scorer 95 sur PSI et avoir quand même un LCP mauvais dans les données CrUX. Ne confonds pas les deux.Core Web Vitals documentation from Google is clear that field data, what real users experience, measured in Chrome User Experience Report, is what Google actually uses for ranking signals. Lab data from PageSpeed Insights is directional, not definitive. I've seen sites score 95 on PSI and still have Poor LCP in CrSX data. Don't confuse the two.

Les Trois Vrais Coupables sur les Sites de Listing

Sur chaque gros site que j'ai audité (et j'en ai parcouru des centaines à ce stade), les défaillances LCP remontent presque toujours à trois causes profondes :

  • Images héros ou de cartes non optimisées, souvent servies en pleine résolution, format incorrect, pas d'indice fetchpriority, often served at full resolution, wrong format, no fetchpriority hint
  • Scripts tiers bloquant le rendu, traceurs d'affiliation, réseaux publicitaires, widgets de comparaison chargeant avant que le navigateur ne puisse afficher quoi que ce soit, affiliate trackers, ad networks, comparison widgets loading before the browser can paint anything
  • TTFB gonflant le budget LCP, réponse serveur lente mangeant 600-900ms avant que la page commence même à se charger, slow server response eating 600-900ms before the page even starts loading

Celui-là, c'est celui que les gens sous-estiment. Si ton TTFB est de 700ms, tu as déjà dépensé près de la moitié de ton budget LCP « Bon » avant que le navigateur ait rendu un seul pixel. Le choix d'hébergement et la mise en cache côté serveur ne sont pas des préoccupations DevOps, ce sont des préoccupations SEO.

---

Commencez par le TTFB : C'est d'abord un problème d'hébergement et de mise en cache

Le projet de type HostList dont j'ai parlé plus haut ? La première chose que j'ai faite a été d'exécuter WebPageTest à partir de cinq emplacements géographiques différents. Le TTFB était constamment 680-820ms. Le site était sur un hébergement mutualisé en Virginie. La plupart de leur trafic organique provenait du Royaume-Uni et d'Allemagne.WebPageTest from five different geographic locations. TTFB was consistently 680-820ms. The site was on a shared host in Virginia. Most of their organic traffic came from the UK and Germany.

Je les ai déplacés vers un hébergeur WordPress géré avec des nœuds de périphérie à Londres et Francfort. J'ai configuré la mise en cache de page complète avec des durées de cache de 12 heures sur les pages de liste (les données ne changeaient pas si souvent de toute façon). Le TTFB est tombé à 120-180ms sur les demandes répétées, 280-350ms sur les défauts de cache à première visite. Ce seul changement a réduit d'environ 500ms le LCP avant que je ne touche à une seule image.WordPress host with edge nodes in London and Frankfurt. Configured full-page caching with cache lifetimes of 12 hours on listing pages (the data didn't change that often anyway). TTFB dropped to 120-180ms on repeat requests, 280-350ms on first-hit cache misses. That single change shaved roughly 500ms off LCP before I touched a single image.

Quelques points que je vérifie toujours du côté de l'hébergement:

  1. La mise en cache full-page fonctionne-t-elle réellement? Vérifiez l'en-tête de réponse X-Cache. Si elle affiche MISS à chaque requête, votre couche de cache ne fonctionne pas. Check the X-Cache response header. If it says MISS on every single request, your caching layer isn't functioning.
  2. Le serveur d'origine est-il géographiquement proche de votre audience principale? Ça semble évident. Vous seriez surpris de la fréquence à laquelle ça ne l'est pas. This sounds obvious. You'd be surprised how often it's wrong.
  3. Le keep-alive est-il activé? Certains hébergeurs bon marché désactivent encore les connexions persistantes. Étonnant en 2024, mais ça arrive. Some cheaper hosts still disable persistent connections. Wild in 2024, but it happens.
  4. HTTP/2 ou HTTP/3 sont-ils actifs? Lancez curl -I --http2 https://yourdomain.com et vérifiez le protocole dans la réponse. Run curl -I --http2 https://yourdomain.com and check the protocol in the response.

Ne touchez pas à l'optimisation des images tant que vous n'avez pas résolu le TTFB. Optimiser les images sur un serveur lent, c'est comme peindre une maison qui brûle.

---

Le problème LCP Image (Et pourquoi `fetchpriority` change tout)

D'accord. Les images. Sur un site d'annonces avec des mises en page en grille de cartes, l'élément LCP est presque toujours la première image de carte au-dessus du pli, ou la bannière héros. Le navigateur doit la découvrir, la récupérer, la décoder et la rendre. Chacune de ces étapes peut être retardée.

Voici ce que nous avons réellement fait sur le projet HostList, dans cet ordre :

  1. Conversion de toutes les images de carte en WebP avec la conversion en masse d'Imagify. La taille moyenne des fichiers a diminué de 58 % sans perte de qualité visible aux résolutions de miniature que nous utilisions (280×180px à l'affichage, servis en 2x pour retina)., using Imagify's bulk conversion. Average file size dropped 58% without visible quality loss at the card thumbnail sizes we were using (280×180px display, served at 2x for retina).
  2. Ajout de `fetchpriority="high"` à la première image de carte. Ce seul changement a réduit d'environ 200ms le LCP mesuré dans WebPageTest. Le navigateur arrête de la traiter comme une image lazy ordinaire et la met en file d'attente immédiatement dans le preload scanner., This one change alone knocked ~200ms off measured LCP in WebPageTest. The browser stops treating it like a regular lazy image and queues it immediately in the preload scanner.
  3. Suppression de `loading="lazy"` des deux premières rangées d'images de carte. Le lazy loading est excellent pour les images en bas de page. Sur la première rangée visible, il vous fait activement du tort. Il dit au navigateur de ne pas charger l'image jusqu'à ce qu'elle soit près de la fenêtre d'affichage, ce qu'elle est déjà., Lazy loading is brilliant for below-fold images. On the first visible row, it actively hurts you. It tells the browser to not fetch the image until it's near the viewport, which it already is.
  4. Ajouté une balise `<link rel="preload">` pour l'image héros dans le `<head>` sur le modèle de page d'accueil spécifiquement. in the <head> on the homepage template specifically.

Cette séquence a ramené le LCP de la page d'accueil de 3,1s à 1,4s en conditions de lab. Les données de terrain ont suivi dans environ 28 jours (c'est à peu près le temps qu'il faut aux données CrUX pour refléter les changements à grande échelle).

Une remarque sur les images responsives

Si vous servez la même image de 1400px de large à un appareil mobile, vous brûlez de la bande passante et ajoutez du temps de décodage. Utilisez srcset correctement. Je sais que cela semble une conversation de 2016, mais je le vois probablement sur 40 % des sites qui passent chez Seahawk. La fonction WordPress wp_get_attachment_image() génère srcset automatiquement, mais seulement si l'image a été téléchargée à une résolution suffisante et que le thème ne l'a pas supprimée avec add_filter('max_srcset_width', ...).srcset properly. I know this sounds like a 2016 conversation but I still see it on probably 40% of the sites that come through Seahawk. The WordPress wp_get_attachment_image() function generates srcset automatically, but only if the image was uploaded at sufficient resolution and the theme hasn't suppressed it with add_filter('max_srcset_width', ...).

---

Scripts bloquant le rendu : la taxe des sites d'affiliation

Les sites de comparaison d'hébergement et les plateformes de listes vivent des revenus d'affiliation. Cela signifie des scripts de suivi tiers. Commission Junction, Impact, Awin, des pixel trackers personnalisés, ils s'accumulent. J'ai compté 14 origines de scripts tiers séparées sur un seul site de listes. Chaque one représente une recherche DNS distincte, une connexion TCP et une poignée de main TLS avant qu'un seul octet de ce script ne soit reçu.

La solution n'est pas de supprimer les scripts. Vous ne pouvez pas, les revenus en dépendent. La solution est la séquençage.

Aucun script tiers ne devrait jamais bloquer le rendu initial de l'élément LCP. Point final.

En pratique, cela signifie :

  • Déplacer tous les scripts d'affiliation et d'analyse pour les charger après l'événement DOMContentLoaded, pas dans <head>.after the DOMContentLoaded event, not in <head>.
  • Utiliser les attributs async ou defer sur chaque script que tu contrôles.async or defer attributes on every script you control.
  • Pour les scripts que vous ne contrôlez pas (injectés par des gestionnaires de balises), chargez Google Tag Manager lui-même avec defer. Oui, c'est sûr pour la plupart des cas d'utilisation du suivi d'affiliation, et la documentation de GTM reconnaît elle-même cette approche.defer, yes, this is safe for most affiliate tracking use cases, and GTM's own documentation acknowledges this approach.
  • Utiliser un gestionnaire de scripts comme Asset CleanUp Pro ou la fonctionnalité de délai de script de WP Rocket pour différer les tiers non essentiels jusqu'à une interaction utilisateur (premier défilement ou premier clic).

Lors de la reconstruction de HostList, le report des scripts tiers a réduit le Total Blocking Time de 1 840 ms à 290 ms. Le TBT n'est pas directement une Core Web Vital, mais il est fortement corrélé à l'INP, qui l'est.is.

---

Chargement de polices : le tueur silencieux de LCP dont personne ne parle

Les polices personnalisées provoquent un mode de défaillance spécifique. Le navigateur affiche votre mise en page, atteint l'élément de texte LCP (parfois LCP est un titre, pas une image), puis attend le fichier de police avant de l'afficher. C'est ce qu'on appelle Flash of Invisible Text, et cela retarde le LCP de 200 ms à plus d'une seconde selon la taille du fichier de police et la proximité du serveur.

Deux choses corrigent cela :

  • `font-display: swap` dans votre déclaration @font-face. Le navigateur rend immédiatement avec une police de secours et effectue l'échange quand la police personnalisée se charge. Le candidat LCP s'affiche à temps. in your @font-face declaration, the browser renders in a fallback font immediately and swaps when the custom font loads. LCP candidate gets painted on time.
  • Auto-hébergez vos polices. Google Fonts ajoute une demande cross-origin. L'auto-hébergement avec l'outil google-webfonts-helper vous permet de servir les polices depuis votre propre domaine, éliminant cette connexion supplémentaire.google-webfonts-helper tool lets you serve fonts from your own domain, cutting that extra connection.

J'ai converti un grand annuaire hors de Google Fonts en environ 45 minutes en utilisant cet outil. Le LCP s'est amélioré de 180 ms. Pas transformateur seul, mais combiné avec tout le reste, ces marges s'accumulent.

---

Mesurer ce qui compte vraiment sur le terrain

Les données CrUX sont la vérité absolue. Mais elles ne se mettent à jour que mensuellement et seulement pour les URL ayant un trafic suffisant. Pour les grands sites avec des milliers de pages, vous avez besoin de quelque chose de plus granulaire.

J'utilise l'API PageSpeed Insights scriptée sur un échantillon représentatif d'URL, généralement les 100 pages principales par trafic, 50 pages de niveau catégorie, et 20 pages profondes "fines" du catalogue. L'exécution mensuelle donne une distribution de performance appropriée, pas un score ponctuel.PageSpeed Insights API scripted across a representative sample of URLs, typically the top 100 pages by traffic, 50 category-level pages, and 20 "thin" deep-catalogue pages. Running this monthly gives a proper performance distribution, not a single-point score.

Dans Lighthouse CI (que nous exécutons dans les pipelines CI/CD pour les clients qui ont des cycles de développement), nous définissons des assertions sur :

  • LCP ≤ 2,5s en lab (objectif conservateur, car le field a tendance à accuser un retard de 10-15% sur le lab)
  • TBT ≤ 300ms
  • CLS ≤ 0,1

Mais honnêtement, pour une construction de type HostList où l'objectif est un LCP inférieur à 1,5s, les cibles de lab doivent être plus strictes. Nous définissons LCP ≤ 1,8s dans Lighthouse CI pour ces projets, ce qui produit généralement 1,3-1,5s dans les données de terrain une fois que CrUX rattrape son retard.

---

Tout Assembler : Le Résultat HostList

Après avoir appliqué tout ce qui précède, migration d'hébergement, cache pleine page, conversion de formats d'images, fetchpriority sur les candidats LCP, suppression du lazy-load des lignes au-dessus de la pliure, report des scripts, et auto-hébergement des polices, voici à quoi ressemblaient les chiffres :fetchpriority on LCP candidates, lazy-load removal from above-fold rows, script deferral, and font self-hosting, here's what the numbers looked like:

  • TTFB : 780ms → 160ms (médiane, visiteurs au Royaume-Uni): 780ms → 160ms (median, UK visitors)
  • LCP (lab, mobile) : 4,2 s → 1,4 s: 4.2s → 1.4s
  • LCP (field, CrUX, 75e percentile) : 3,8 s → 1,6 s (mesuré 60 jours après la migration): 3.8s → 1.6s (measured 60 days post-migration)
  • TBT : 1 840 ms → 290 ms: 1,840ms → 290ms
  • CLS : était déjà bon à 0,03, inchangé: was already fine at 0.03, unchanged

Tous les sites ne bénéficieront pas d'une amélioration de 2,8 secondes. Mais presque tous les grands sites d'annonces sur lesquels j'ai travaillé avaient tous ces problèmes simultanément, ce qui signifie que les gains s'accumulent. Corriger une chose et vous gagnez 300 ms. Corriger toutes et vous gagnez 2,5 secondes.

---

FAQ

L'hébergement compte-t-il vraiment autant pour le LCP ?

Oui, probablement plus que n'importe quoi d'autre au départ. Si votre TTFB est au-dessus de 500ms, aucune optimisation d'image ne vous permettra d'atteindre un LCP « Bon ». TTFB est la fondation sur laquelle tout le reste repose. Amenez-le d'abord en dessous de 200ms, puis préoccupez-vous du reste.

Dois-je utiliser un CDN au lieu de migrer d'hébergement ?

Un CDN aide à la livraison des assets statiques et peut réduire le TTFB pour le HTML en page complète mis en cache s'il est configuré correctement. Mais de nombreuses configurations CDN ne cachent que les assets, pas les réponses HTML complètes. Vérifiez si votre CDN sert réellement du HTML mis en cache ou s'il décharge seulement les images. Si c'est ce dernier cas, un meilleur serveur d'origine fera plus pour le LCP.

`fetchpriority="high"` est-il largement supporté maintenant ?

Depuis 2024, oui, c'est supporté dans Chrome, Edge, et Safari (depuis Safari 17.2). Le support de Firefox est arrivé dans Firefox 132. Pour les navigateurs qui ne le supportent pas, c'est ignoré sans danger. Il n'y a aucun inconvénient à l'ajouter à votre élément d'image LCP.

Combien de temps faut-il aux données CrUX pour refléter les améliorations ?

Environ 28 jours à partir du moment où les vrais utilisateurs commencent à expérimenter la version plus rapide du site. CrUX utilise une fenêtre glissante de 28 jours. Donc si vous déployez des changements aujourd'hui, votre score de données terrain ne les reflètera pleinement que dans environ un mois. Ne paniquez pas si PageSpeed Insights affiche toujours « À améliorer » le lendemain de votre sprint d'optimisation.

Quel est le changement au plus fort impact pour un site d'annonces ?

Sur pratiquement tous les projets, c'était le TTFB. Mais le deuxième facteur le plus élevé a régulièrement été la suppression de loading="lazy" des images de carte au-dessus de la ligne de flottaison et l'ajout de fetchpriority="high". Ces deux choses représentent généralement à elles seules 40-60% de l'amélioration totale du LCP. Tout le reste est des gains composés en plus de cette fondation.loading="lazy" from above-fold card images and adding fetchpriority="high". Together those two things usually account for 40-60% of the total LCP improvement. Everything else is compounding gains on top of that foundation.

---

Le travail de performance sur les gros sites, c'est surtout de la plomberie. Peu glamour, méthodique, et profondément satisfaisant quand vous faites descendre un LCP de 4 secondes à 1,4 secondes et que vous voyez le trafic organique augmenter deux mois plus tard. Il n'y a pas de paramètre magique unique, juste une séquence de décisions spécifiques prises dans le bon ordre.

Rendez le serveur rapide. Ensuite, faites découvrir et charger l'élément LCP tôt. Puis écartez tout le reste de son chemin.

< BACK