On parle beaucoup des plugins de cache, des CDN, des images en WebP. On parle rarement de la décision, en amont de toutes les autres, qui détermine le reste : le thème. Avant la moindre ligne de contenu, votre thème fixe ce qu'un navigateur devra télécharger, analyser, compiler et exécuter pour peindre la page. Et parmi tous ses choix techniques, un pèse plus que les autres sur la vitesse : la façon dont il livre son JavaScript.
Il existe deux familles. Les thèmes qui découpent leur code en petites pièces chargées à la demande, et les thèmes qui empilent tout dans un seul bloc, le fameux main.js, theme.js ou bundle.min.js qui pilote le menu, le slider, la lightbox, les onglets, les formulaires, les animations au scroll et les appels AJAX. Cette seconde famille vous enferme sous un plafond de performance bas. Voici pourquoi, et comment le repérer avant de vous engager.
Optimiser finement, c'est pouvoir découper
Une bonne optimisation front-end n'est jamais un simple interrupteur. C'est un travail chirurgical : garder ce qui est visible immédiatement, repousser le reste, supprimer ce qui n'est pas utilisé du tout. Concrètement, sur une page bien optimisée, on veut pouvoir :
- Charger le strict minimum pour que le haut de la page (l'ATF, au-dessus de la ligne de flottaison) soit peint et interactif le plus vite possible.
- Retarder tout ce qui n'est pas nécessaire tout de suite (un carrousel de pied de page, un chat, un widget de partage) jusqu'à la première interaction ou au premier scroll.
- Ne pas charger du tout ce qui n'apparaît pas sur la page courante (le script de galerie sur une page qui n'a pas de galerie).
Ces trois leviers partagent un même prérequis : le code doit être découpable. Vous ne pouvez retarder une pièce que si elle existe en tant que pièce. Vous ne pouvez écarter un script conditionnel que s'il a été chargé conditionnellement. Toute la finesse tient là. Un thème monolithique supprime le prérequis. Il n'y a plus de pièces, il y a un bloc.
Anatomie d'un monolithe
Ouvrez l'onglet Network d'un site, filtrez sur JS, et regardez le poids du plus gros fichier que livre le thème. Sur un thème monolithique, vous verrez un seul fichier qui concentre l'essentiel :
acme-theme/assets/js/main.min.js 287 KB <- everything
jquery.min.js 89 KB
jquery-migrate.min.js 13 KBCe fichier ne fait pas une chose. Il en fait vingt. Et surtout, elles sont câblées les unes aux autres dans la même portée, la même closure, la même chaîne de dépendances jQuery. Le menu déroulant partage son init avec le slider hero, qui partage le sien avec le module de témoignages, qui dépend d'un plugin de scroll, qui dépend de jQuery, qui dépend de jQuery Migrate. Retirez une brique et les autres tombent.
C'est là que la stratégie d'optimisation se heurte au mur. Reprenons nos trois leviers. Tout retarder : vous pouvez repousser le bloc entier jusqu'à la première interaction, mais alors la première interaction (un simple clic sur le menu burger) paie, d'un coup, le téléchargement, l'analyse, la compilation et l'exécution des 287 Ko complets. L'utilisateur clique, et rien ne répond pendant que le thread principal digère un carrousel dont il n'a aucun usage. Vous avez déplacé le problème, vous ne l'avez pas résolu. Ne rien retarder : le bloc s'exécute au chargement, gonfle le TBT (Total Blocking Time), retarde l'interactivité, et s'il touche au DOM au-dessus de la ligne de flottaison, dégrade le LCP. Découper finement : impossible, il n'y a rien à découper. C'est tout ou rien.
Le vrai coût, c'est l'analyse, pas le téléchargement
Une idée reçue tenace : « 300 Ko de JS compressé, ça va, c'est rien à télécharger. » Le téléchargement n'est pas le problème principal. Le JavaScript a un coût que les images n'ont pas : il doit être analysé, compilé et exécuté sur le thread principal, celui-là même qui doit répondre aux interactions de l'utilisateur.
Un octet d'image se décode sur un thread annexe. Un octet de JS bloque potentiellement l'interactivité. Sur un mobile de milieu de gamme, analyser et exécuter 300 Ko de JS applicatif se mesure en centaines de millisecondes, pas en poids réseau. Et un monolithe vous fait payer ce coût en totalité, pour du code qui, 80 % du temps, n'a rien à voir avec la page à l'écran.
« Mais un seul fichier, c'est mieux pour HTTP/2, non ? »
Une objection légitime, et elle mérite une réponse honnête plutôt qu'un revers de main. Oui, historiquement, réduire le nombre de requêtes était une bonne pratique, et oui, concaténer avait du sens en HTTP/1.1. Mais deux choses ont changé. D'abord, HTTP/2 et HTTP/3 multiplexent : plusieurs petits fichiers en parallèle ne coûtent plus le prix des requêtes séquentielles d'antan. L'argument « moins de requêtes » a largement perdu de sa force.
Ensuite, et c'est le point décisif, le vrai coût du JS n'est pas la requête, c'est l'exécution. Dix petits scripts dont vous n'en exécutez que deux coûtent bien moins qu'un seul gros que vous exécutez en entier. La granularité n'est pas là pour faire plus de requêtes, elle est là pour exécuter moins de code. C'est un tout autre bénéfice, et il survit parfaitement à HTTP/2.
Trois cas concrets
Cas A : le carrousel fantôme
Un thème tout-en-un charge son bundle complet sur chaque page, carrousel compris. Mais le carrousel n'existe que sur la page d'accueil.
Sur les 40 pages d'articles du blog, ce code est téléchargé, analysé, compilé, et jamais utilisé. L'onglet Coverage de Chrome le confirme : 60 à 80 % du fichier est marqué « unused ».
Un thème modulaire n'aurait tout simplement pas chargé ce script en dehors de la page d'accueil.
Cas B : le menu pris en otage
Un site veut retarder son JavaScript non critique. Problème : le menu burger mobile et la lightbox de galerie vivent dans le même fichier.
Retardez le fichier et vous cassez le menu, l'élément le plus critique de l'au-dessus de la ligne de flottaison sur mobile. Ne le retardez pas et la lightbox, inutile au chargement, reste dans le chemin critique.
Le couplage interdit la seule décision qui aurait du sens : le menu maintenant, la lightbox plus tard.
Sur un tel thème, le symptôme classique est un menu burger qui ne s'ouvre qu'au deuxième appui. La méthode générale pour trouver quel script un report a cassé se trouve dans notre guide sur le report du JavaScript.
Cas C : le contre-exemple qui fonctionne
Un thème bien construit charge un petit script de navigation (quelques Ko, sans dépendance à jQuery) pour le menu, et ne charge le script de galerie que sur les pages qui contiennent une galerie, avec un defer.
Le menu est instantané. La galerie se charge séparément, se retarde sans rien casser, et disparaît entièrement des pages qui n'en ont pas.
Ici, la plateforme d'optimisation a de quoi travailler : elle peut opérer dans le grain fin parce que le thème lui a laissé des prises.
// Menu : minuscule, sans jQuery, toujours nécessaire
wp_enqueue_script( 'acme-nav', $uri.'/nav.js', array(), null, true );
// Galerie : seulement là où il y a vraiment une galerie, en différé
if ( has_block( 'core/gallery' ) ) {
wp_enqueue_script( 'acme-gallery', $uri.'/gallery.js', array(), null, true );
}Comment repérer un monolithe avant de vous engager
Vous pouvez auditer un thème en quelques minutes, sur sa démo, sans même l'installer.
- Onglet Network, filtre JS. Regardez le plus gros fichier que livre le thème. Un seul fichier de 150 Ko ou plus, présent sur chaque page, est un signal d'alarme. Plusieurs fichiers de taille modeste est bon signe.
- Onglet Coverage (dans DevTools, « Coverage »). Rechargez la page et lisez le pourcentage « Unused ». Si le gros script affiche 60 % ou plus de code inutilisé sur une page interne, le thème charge trop, partout, sans conditions.
- Le test de la page nue. Comparez le JS chargé sur la page d'accueil et sur une page de contact minimaliste. Si c'est exactement le même bundle, le thème ne charge rien conditionnellement. Il déverse tout, tout le temps.
- La dépendance à jQuery. Un thème qui empile jQuery, jQuery Migrate et une pile de plugins jQuery dans une seule chaîne est presque toujours monolithique dans l'esprit, même quand il découpe ses fichiers. Ces dépendances se tiennent par la main et refusent d'être découpées.
- La lecture du code, si accessible. Regardez comment les scripts sont enregistrés. Un seul
wp_enqueue_scriptglobal sans condition de page ni de composant dit tout. Un thème sérieux charge ses scripts au plus près des composants qui les utilisent, et sous conditions.
Ce qui fait un bon thème, côté JS
- Des assets granulaires : plusieurs scripts ciblés plutôt qu'un seul bloc unique.
- Un chargement conditionnel : un script n'est présent que sur les pages qui utilisent son composant.
- Une faible dépendance à jQuery, idéalement du JavaScript natif pour les briques critiques comme le menu.
- Différable par nature : le code peut être repoussé sans casser l'au-dessus de la ligne de flottaison, parce que l'au-dessus de la ligne de flottaison n'en dépend pas.
- Rien d'inutile exécuté au chargement pour le haut de la page.
- Des hooks propres, qui laissent une plateforme d'optimisation supprimer, retarder ou remplacer une pièce sans effets de bord.
Aucun de ces points ne concerne le « poids » du thème au sens marketing. Ils concernent tous la découpabilité. Voilà la vraie métrique.
Le fin mot
Optimiser un site, c'est faire des choix fins, page par page, composant par composant : celui-ci maintenant, celui-là plus tard, ce troisième jamais. Ces choix supposent que le thème a livré son code en pièces que vous pouvez manipuler séparément. Un thème monolithique ne livre pas de pièces, il livre un bloc soudé, et vous condamne au tout ou rien.
Une plateforme d'optimisation peut faire beaucoup même dans ce cas : servir un cache, différer en bloc ce qui peut l'être, alléger les images, stabiliser la mise en page. Mais elle ne peut pas défaire un couplage écrit dans le code du thème. Le plafond a été fixé en amont, au moment où le thème a été choisi.
Mantys Core fait son travail le plus fin sur les thèmes granulaires, et aide encore sur les monolithiques :
Sur un thème découpable, il garde l'au-dessus de la ligne de flottaison minimal et retarde le reste jusqu'à l'interaction ou au scroll, page par page.
Il retire le CSS et le JS que la page courante n'utilise jamais, et diffère ce qui peut l'être.
Sur un monolithe, il met quand même en cache, stabilise la mise en page et diffère en bloc, mais c'est le thème qui fixe le plafond.
Choisir un thème découpable, c'est choisir un plafond plus haut. Tout ce qui vient ensuite se compose à partir de là.
Commentaires
Vous butez sur un problème similaire ? Décrivez votre configuration et ce que vous observez. Nous lisons chaque commentaire et nous répondons.
Aucun commentaire pour l’instant. Partagez le premier votre cas.