optimisation core web vitals 7 min

Structure page WordPress : pourquoi ton DOM plombe ton LCP avant le backend

Un site WooCommerce avec 4 200 nœuds DOM, un LCP à 6,8 s et un CLS à 0,35. On a divisé le DOM par 4 sans changer le design. Voici comment l'empilement de blocs Gutenberg et de plugins tue vos Core Web Vitals, et la méthode pour y remédier.

Par Julien Morel
Partager

Un site WooCommerce, 120 plugins actifs dont la moitié maintenus approximativement, un thème enfant qui surcharge chaque template. Résultat dans la Search Console : LCP à 6,8 secondes sur la page d’accueil, CLS à 0,35, INP à 380 ms. Le client nous envoie la capture Lighthouse en croyant à un souci d’hébergement. Le TTFB est à 180 ms. Le problème n’est pas le serveur, il est dans le code HTML que WordPress envoie au navigateur : 4 200 nœuds DOM pour générer ce qui ressemble à une page d’accueil plutôt banale.

On te répète qu’un bon plugin de cache, un CDN et des images optimisées règlent l’essentiel. C’est vrai sur un site vitrine qui affiche 300 nœuds. Sur un site qui utilise Gutenberg ou un page builder sans contrôle, le cache masque une montagne de code superflu qui continue à coûter cher au moment du rendu. L’intention de recherche derrière « structure page WordPress » est rarement un cours d’anatomie : c’est un admin qui voit ses indicateurs dans le rouge et qui cherche ce qui, dans le markup, écrase le LCP. On va le prendre par là.

Le cache efface la latence, pas les nœuds

Un cache HTTP, qu’il soit côté serveur via WP Rocket ou en edge, réduit le TTFB. Tant mieux. Mais le LCP et l’INP mesurent ce qui se passe une fois le HTML arrivé dans le navigateur : le parsing, le calcul de style, le layout, la composition et l’exécution JavaScript. Si votre HTML contient 4 200 nœuds DOM parce que chaque section est enrobée dans six <div> avant d’afficher un titre et un paragraphe, le navigateur va construire un arbre énorme, appliquer les styles à chaque nœud, calculer leurs positions, tout ça avant de pouvoir afficher le moindre élément au-dessus de la ligne de flottaison.

Sur le site audité, on a isolé le temps passé en recalcul de style et en layout : cumulé, plus de 500 ms sur mobile. Le TTFB, lui, plafonnait à 200 ms. Optimiser le backend davantage n’aurait presque rien changé. C’est contre-intuitif parce qu’on nous a formés à mesurer la rapidité du serveur. La réalité des Core Web Vitals, c’est que le temps de rendu domine souvent le temps de chargement une fois passé un seuil de performance serveur correct. Un DOM maigre peut pardonner un TTFB médiocre. L’inverse est faux.

J’ouvre une parenthèse pour ceux qui bossent aussi sur des stacks JavaScript : quand on traque un LCP dans une app React, on va inspecter des composants et leur gestion d’état. Le problème est le même, mais la granularité est différente. Là où un state manager comme Zustand contrôle finement les re-rendus, WordPress balance tout d’un bloc. Ce qui est une évidence pour un dev front habitué aux DevTools l’est moins pour quelqu’un qui administre un CMS et qui pense que le cache efface tout. Il n’efface que ce qui se passe avant le premier octet.

Gutenberg fabrique des wrappers par paquets de dix

Prenez un bloc Colonnes avec deux colonnes, chacune contenant un titre, un paragraphe et un bouton. Le rendu final affiche trois éléments visibles : un titre, un texte, un bouton, et le même dans l’autre colonne. Le DOM généré, lui, avoisine les 60 ou 70 nœuds, une fois comptées les imbrications de blocs internes, les div de conteneur flex, les wrappers de groupe invisibles. Multipliez par huit sections sur une page d’accueil et vous dépassez les 500 nœuds uniquement pour la structure décorative, avant même d’avoir rendu le contenu réel.

On ne peut pas le voir si on se contente du front-end visuel. Ouvrez l’onglet Éléments des DevTools et dépliez manuellement l’arbre : chaque bloc natif embarque un système de classes CSS, des conteneurs machine et des hooks markup pour le back-end qui ne servent à rien côté public. WordPress fonctionne ainsi pour rester extensible. Mais sur la page finale, cette extensibilité est mort-née : personne ne va cloner un bloc en front, ce markup supplémentaire est un poids mort.

La parade n’est pas de fuir Gutenberg. Elle consiste à réduire le nombre de blocs imbriqués et à remplacer les assemblages complexes par un bloc HTML personnalisé quand le contenu le permet. Un développeur qui maîtrise le squelette de son thème peut aussi créer des modèles de blocs allégés, avec un render_callback qui nettoie le markup inutile. Le gain est immédiat : on a retiré 1 200 nœuds sur la homepage du client en convertissant six sections de “design” en strates d’HTML propre, gardant exactement le même aspect visuel. Le LCP est descendu à 2,2 secondes, le CLS sous 0,1.

Ce chantier n’est pas glamour. Il demande d’ouvrir des templates PHP ou des fichiers JSON de blocs, de comprendre ce que chaque fonction d’affichage produit et de savoir lire du HTML en diff git. Pourtant c’est le levier le plus massif pour des Core Web Vitals corrects sur WordPress : aucun plugin d’optimisation ne peut retirer le markup après-coup sans risquer de casser l’affichage. Soit on l’allège en amont, soit on le subit.

Pourquoi vos plugins chargent leur fat JS sur la page de connexion

Le deuxième cancer du DOM WordPress n’est pas le markup seul, c’est l’accumulation de CSS et JS parasites. Installez un plugin de slider pour la home, son script et sa feuille de styles se chargeront aussi sur la page contact, la page panier, l’article de blog. Même combat pour un formulaire, une popup newsletter, un plugin de partage social. Au bout de trente extensions, le navigateur télécharge 80 fichiers CSS et JS, dont une poignée seulement sont utilisés sur la page en cours.

Le problème ne touche pas que le LCP. Il frappe l’INP, ce délai qui mesure le temps entre une interaction utilisateur et la réponse visuelle du navigateur. Un fichier JS non nécessaire qui s’intercale dans la file d’exécution peut retarder le traitement de l’événement d’un clic. Sur mobile, ce retard se transforme en expérience pâteuse. Et l’utilisateur ne sait pas que c’est le plugin de chat en ligne qui met 150 ms à répondre alors qu’il n’y a même pas de chat sur la page.

Corriger cet empilement demande une approche chirurgicale : lister chaque asset enregistré par WordPress via wp_enqueue_scripts, associer chaque script ou style à la page où il est réellement nécessaire, et désenregistrer ce qui n’a rien à faire ailleurs. Avec des fonctions conditionnelles, on peut dire à WordPress de ne charger le slider que si la page d’accueil est affichée, de ne livrer le style du formulaire que sur la page de contact. Cela suppose un thème maintenu par quelqu’un qui sait coder un wp_dequeue_script dans functions.php, pas seulement cocher des cases dans un panneau de réglages. L’alternative paresseuse, c’est un plugin qui combine et minifie tout sans discernement, et qui déplace la dette sans l’effacer.

Quand on bascule d’un workflow WordPress à une app React, la gestion du chargement conditionnel redevient native : la navigation côté client découpe les bundles. Un state manager comme Zustand, qui pèse quelques kilo-octets, n’alourdit pas le chargement initial. C’est ce genre de finesse qui manque à un WordPress laissé sans contrôle. Une architecture trop permissive finit toujours par affamer le navigateur, quel que soit le CMS.

Quand le CLS provient d’un bloc réservé au back-office

Un symptôme trop méconnu : des blocs réservés à l’édition visuelle, chargés d’injecter des styles ou des scripts de back-office, laissent traîner dans le DOM des conteneurs vides en production. Le pire exemple qu’on ait vu : un bloc “ancre de menu” personnalisé qui générait un <div> avec une règle CSS en position: relative et un height calculé par JavaScript. Sur le front-end, ce div ne contenait rien, mais poussait le layout et créait un décalage de 20 px à chaque chargement de page. Le CLS est resté bloqué à 0,25 pendant des semaines avant qu’on ne l’identifie.

Le diagnostic est simple en théorie, fastidieux en pratique : parcourez le DOM avec l’onglet Éléments, repérez tous les éléments vides ou ceux dont le style injecté modifie la mise en page sans raison fonctionnelle. Parfois, une classe CSS générée par un plugin disparu continue de charger via le cache d’un autre. Une méthode fiable : désactiver les plugins un par un en environnement de staging, capturer un film Lighthouse à chaque étape, et surveiller les sauts de score.

Les articles généralistes vous diront d’utiliser un plugin de cache. Nous, on vous dit de commencer par la structure HTML brute. Le CLS est un signal de classement documenté par Google, pas une variable d’ambiance. Un thème enfant bien construit peut verrouiller les dimensions des conteneurs clés et interdire à un bloc erratique de redimensionner la page. C’est plus efficace que de croiser les doigts pour que le navigateur compense.

La checklist de chirurgie DOM qu’on applique avant tout test de performance

Avant d’ouvrir Lighthouse, on passe trente minutes sur cet enchaînement. Il n’y a pas de magie, juste de la discipline.

Réduire le nombre total de nœuds DOM en dessous de 1 500 sur les pages principales. Si la page d’accueil dépasse ce seuil, identifiez les blocs natifs les plus lourds et migrez-les vers des templates simplifiés. Un bloc Colonnes peut devenir une grille CSS écrite en dur dans un bloc HTML personnalisé, sans aucun wrapper superflu.

Désenregistrer les styles et scripts inutiles page par page. Un fichier functions.php propre contient une série de conditions if( !is_front_page() ) et wp_dequeue_style() explicites. Ce n’est pas du bidouillage, c’est du contrôle d’actifs.

Nettoyer les restes de plugins désinstallés. Certains laissent des options, des métadonnées et des hooks qui continuent d’injecter du markup mort. Un audit avec WP-CLI et des requêtes SQL ciblées permet de purger ces traces.

Vérifier que chaque image au-dessus de la ligne de flottaison a une hauteur et une largeur explicites pour prévenir les redimensionnements tardifs. Ce n’est pas un problème de DOM, mais un problème de structure qui déclenche du CLS supplémentaire.

Toutes ces actions sont gratuites, n’exigent aucun abonnement à un service tiers, et ne dépendent pas d’une mise à jour de plugin. Elles exigent en revanche qu’on traite le code généré comme une surface de travail, pas comme une fatalité. Dans une stack moderne, on n’accepterait jamais de livrer autant de markup inutile ; WordPress ne doit pas être une exception.

Pour traquer les nœuds en excès, on alterne entre les DevTools et son éditeur. Que vous utilisiez Cursor ou que vous préfériez Claude Code pour du refactoring rapide, l’important est d’avoir un terminal ouvert sur le thème enfant et de pouvoir vérifier chaque suppression en direct. Le DOM, c’est du code comme un autre, ça se versionne et ça se nettoie.

Questions fréquentes

Est-ce qu’un bon CDN peut compenser un DOM trop lourd ?

Non. Un CDN réduit la latence réseau et accélère la livraison des assets statiques, mais le navigateur doit toujours parser et mettre en page le HTML téléchargé. Un DOM qui frôle les 2 000 nœuds prendra le même temps de layout, que le fichier vienne d’un edge à 10 ms ou d’un serveur mutualisé. Le CDN améliore le TTFB et le chargement, pas le rendu.

Entre Gutenberg et un page builder comme Elementor, lequel produit le markup le plus propre ?

Les deux peuvent produire des arbres DOM très profonds. Gutenberg a l’avantage d’être natif et de vous laisser injecter des blocs HTML personnalisés sans surcouche. Les constructeurs visuels ajoutent souvent plusieurs niveaux de wrappers supplémentaires pour gérer leurs propres systèmes de colonnes et d’animations. La différence se fait surtout sur la capacité à simplifier le markup en sortie, quel que soit l’outil choisi.

Peut-on automatiser la chasse aux nœuds inutiles ?

Partiellement. Des outils comme Puppeteer ou Playwright peuvent compter la taille du DOM et repérer des variations après désactivation de plugins. Mais seule une revue manuelle, page par page, identifiera les conteneurs vides ou les styles inutiles qui continuent d’affecter le layout. L’automatisation vous donne le signal, pas le remède.

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.