optimisation core web vitals 7 min

Recettes site internet : l’illusion des bonnes pratiques universelles

Les recettes SEO toutes faites mènent souvent à des sites lents et mal indexés. Voici une approche de diagnostic adaptée à votre stack, pas un énième guide générique.

Par Julien Morel
Partager

On a audité un site qui appliquait cinq « recettes incontournables pour un site rapide » issues d’un article culte partagé 40 000 fois.
LCP à 6,2 secondes. INP à 380 ms. Et 11 000 URLs en « Détectée, actuellement non indexée » dans la Search Console.
Le problème n’était pas la qualité des recettes. Il était dans leur application aveugle, hors sol, sans lecture du stack réel.
C’est de là que vient le titre de cet article. Les recettes site internet vendues comme des modes d’emploi universels sont une fiction technique. Et voici pourquoi ça coûte cher en performance et en indexation.

La recette qui a plombé le LCP à 6 secondes

Le site en question tournait sur un Next.js 14, App Router, rendu hybride. La recette prescrivait : « lazy-load toutes les images, minifie le JS, active la compression Brotli, et mets un CDN devant. » Du conseil standard, vu et revu.
Le problème ? L’image LCP, une bannière héro en plein above the fold, était lazy-loadée avec l’attribut loading="lazy". Résultat : le navigateur a découvert l’image tard, après le parsing du JS, après l’exécution d’un useEffect qui déclenchait un fetch supplémentaire. Le LCP n’a pas été la bannière. Il a été un texte secondaire affiché plus tôt, pendant que la vraie image poireautait.

La minification JS était déjà faite par le build Next. La double compression a créé des artefacts de cache sur le CDN. Et le CDN ne servait pas les bons en-têtes Vary pour le Brotli.
La recette n’était pas fausse. Elle était juste écrite pour un WordPress avec un thème standard. Appliquée à un rendu serveur avec hydration progressive, elle a fabriqué de l’inertie.

⚠️ Attention : le lazy loading natif sur l’image LCP est le piège le plus fréquent qu’on détecte en audit. Google lui-même le déconseille pour l’élément qui détermine le LCP.

Core Web Vitals : le faux ami des recettes qu’on vous ressert

Les Core Web Vitals sont devenus le nouveau jingle des marronniers SEO. On vous les décline en trois métriques, trois seuils, trois actions. Sauf que ces métriques ne sont pas indépendantes. Améliorer un LCP en préchargeant un fichier peut faire bondir l’INP si ce préchargement entre en compétition avec le thread principal au moment de l’hydration.

Prenons le cas du fetchpriority="high". La recette basique dit : « mettez-le sur l’image LCP pour gagner 500 ms. » Vrai sur un site statique. Sur une SPA avec un loader initial, l’image haute priorité se retrouve téléchargée avant que le squelette ne soit affiché, ce qui retarde le premier rendu significatif chez certains navigateurs. On l’a mesuré sur un test avec WebPageTest : le LCP a baissé, mais le Speed Index a grimpé de 1,2 s. Le ressenti utilisateur s’est dégradé.

Autre mythe : il suffit de passer tous les seuils au vert pour que Google classe mieux. Ce que Google documente, c’est une évaluation à la volée de l’expérience de page. Un LCP à 2,4 s avec une mise en page stable peut parfaitement ne pas apporter de gain de positions si le contenu ne répond pas à l’intention. Pourtant, combien de sites sacrifient des contenus éditoriaux pour gratter 100 ms sur une landing page qui n’a jamais été une porte d’entrée organique ?

Ce que votre stack technique fait à la recette

Quand un article vous parle de « recette pour un site rapide » sans mentionner votre runtime, fermez l’onglet. La différence entre un site Astro, un Remix, un Next.js Pages Router et un WordPress Elementor, ce n’est pas le même ordre de grandeur. C’est même l’opposé complet sur certains leviers.

WordPress génère du HTML serveur, mais la couche de plugins ajoute souvent des dépendances CSS et JS qui bloquent le rendu. La recette du « critical CSS inline » y est pertinente. Sur Next.js App Router, le CSS est géré par modules et le framework découpe automatiquement le JS, mais l’hydration peut devenir le point noir. Là où il fallait purger le CSS superflu sur l’un, il faut réduire le nombre de composants client-side sur l’autre.

Un mauvais choix de librairie de state management illustre ce point. Beaucoup de projets React embarquent Redux par habitude, avec un bundle middleware qui alourdit le premier chargement de 20 ko gzippés supplémentaires. Utiliser Zustand pour des besoins simples divise ce poids par trois et simplifie le découpage de code. Ce n’est pas un détail à la marge quand votre INP dépend de combien de millisecondes le thread principal met à traiter chaque interaction.

L’indexation n’est pas un problème de recette, c’est un problème de signal

Sur le même audit, 11 000 URLs détectées mais non indexées. Le site avait un sitemap.xml de 50 000 entrées, tout type confondu : articles, pages d’auteur, archives de tags, pagination. La « recette » classique recommande un sitemap exhaustif. Google, lui, réserve son crawl budget en priorité aux URLs qui portent un signal de qualité.

Segmenter les sitemaps par type de contenu et n’inclure que les URLs canoniques avec un statut 200, c’est la base. Pourtant, peu de sites le font. Ils ajoutent mécaniquement tout ce qui a un slug, pensant qu’un sitemap dodu suffit. Résultat : Googlebot passe du temps sur des pages de pagination profonde, indexe partiellement, et le ratio pages indexées / pages soumises s’effondre.

Autre angle mort : les signaux mous que sont les directives robots dans le HTML. Un noindex sur une page liste filtrée, couplé à un canonical sur la page parente, ça fonctionne. Mais si la page parente est elle-même en noindex à cause d’une règle mal héritée, le signal s’annule. Dans les logs serveur, on voit Googlebot insister sur ces URLs orphelines, perdre du temps, puis les ignorer. Pas de recette miracle. Juste une lecture croisée entre les logs et la Search Console.

📌 À retenir : un sitemap non segmenté et des directives robots incohérentes sont les deux causes les plus fréquentes de déclassement silencieux. On les rate parce qu’elles ne produisent pas d’erreur visible dans la Search Console.

Construisez votre propre diagnostic, pas celui du voisin

Alors, on renonce à toute recette ? Non. Mais on remplace l’idée de recette universelle par une boucle de diagnostic. À chaque projet sa séquence.

D’abord, cartographiez la chaîne critique de rendu. Pas celle du rapport Lighthouse générique. Celle de votre route la plus visitée, mesurée avec l’API CrUX ou un outil de monitoring continu. Ensuite, identifiez le maillon qui bloque le premier rendu. C’est souvent une ressource, mais parfois une exécution JS synchrone. Si vous utilisez un éditeur comme Cursor ou un outil d’assistance comme Claude Code, la génération de code peut insérer des dépendances sans que vous visualisiez leur impact bundle. Sur une codebase Next.js, on a déjà vu un import automatique de lodash entier ajouté par complétion, qui alourdissait le premier chargement de 30 ko. Ce n’est pas la faute de Claude Code ou Cursor : c’est l’absence de revue bundle qui laisse passer ça.

Deuxième étape : mesurez le vrai INP, pas le TBT. Le Total Blocking Time sous-estime souvent les long tasks dues aux animations CSS lourdes sur mobile. Sur un site e-commerce avec un bandeau promotionnel animé, on a vu un INP à 450 ms alors que le TBT restait sous 100 ms. La raison : une animation @keyframes qui repaint toute la page sur un thread déjà chargé. Aucune « recette » n’en parle.

Troisième étape : vérifiez la cohérence de vos signaux d’indexation. Pas juste le robots.txt. Les en-têtes HTTP X-Robots-Tag, les meta robots conflictuelles, les canonicals croisées. Un test simple : prenez dix URLs détectées non indexées, faites un curl -I et comparez avec le rendu de l’URL dans l’outil d’inspection de la Search Console. Vous trouverez presque toujours une incohérence.

La seule règle valable : « ça dépend »

La réponse universelle existe, c’est « ça dépend ». Et ça dépend d’abord de votre delivery, pas de votre framework favori. Avant d’optimiser, définissez si la page doit être servie en statique, en SSR, en ISR ou en rendu client. Chaque choix déplace le point de friction.

Un site Astro avec pré-rendu complet aura un LCP excellent mais ne pourra pas personnaliser par utilisateur. Un Next.js avec ISR peut servir du contenu frais, mais l’hydratation sur une première visite mobile 4G pèsera plus lourd qu’un fichier HTML statique. Il n’y a pas de meilleur mode. Il y a le mode qui correspond à la contrainte métier. Et c’est cette correspondance qui doit guider ce que vous chargez, quand et comment.

Questions fréquentes

Faut-il vraiment éviter toutes les checklists de performance ?

Non, mais elles doivent être spécifiques à votre stack. Une checklist Next.js App Router qui ne parle pas de l’impact des Server Components sur le JS bundle n’a aucun sens. Une checklist WordPress qui ignore l’audit des plugins est inutile. Utilisez les checklists comme un pense-bête, pas comme un plan d’action.

Le lazy loading peut-il nuire au SEO directement ?

Indirectement, oui. Si le contenu principal d’une page (texte ou image) est chargé en différé et que le bot le découvre plus tard, l’extraction des entités sémantiques peut être incomplète. En pratique, Google traite le HTML initial, mais un lazy loading agressif via Intersection Observer peut faire que la version rendue n’est pas identique à la version servie. Vérifiez le rendu dans l’outil d’inspection.

Les outils de monitoring continu remplacent-ils un bon audit manuel ?

Ils le complètent. Un bon audit manuel lit les logs, vérifie les en-têtes, confronte les metrics de terrain (CRuX) aux tests en lab. Les outils de monitoring capturent les dérives, mais ils ne remplacent pas la compréhension architecturale de pourquoi un LCP se dégrade après une release.

Articles similaires

Julien Morel

Julien Morel

Ancien dev front React passé SEO technique après une migration e-commerce qui a fait perdre 60% du trafic organique à son employeur en une nuit (fichier robots.txt oublié en staging). Depuis, il écrit pour que ça n'arrive à personne d'autre et teste sur ses propres side-projects avant de publier quoi que ce soit.

Cet article est publie a titre informatif. Faites vos propres recherches avant toute decision.