Si vos pages Divi 5 mettent 3–8 secondes à s’afficher alors que votre serveur n’est pas saturé, le problème vient souvent d’un mélange explosif : assets chargés partout, requêtes répétées et JavaScript tiers qui bloque le rendu.
Le problème
Le “bug” n’est pas une erreur unique, mais un pattern que je vois souvent sur des sites Divi 5 (WordPress 6.9.4, PHP 8.1+) : le front-end devient lent après avoir ajouté des modules, des scripts marketing, ou après une mise à jour de thème/plugins. Côté admin, le Visual Builder peut aussi être poussif, mais ce billet cible surtout les performances front.
Quand vous activez le debug, vous pouvez retrouver ce genre de signaux dans vos logs (exemples réalistes) :
PHP Warning: Undefined array key "et_pb_pagebuilder" in /wp-content/themes/Divi/includes/builder/frontend-builder/helpers.php on line 123
PHP Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the my-plugin domain was triggered too early.
This is usually an indicator for some code in the plugin or theme running too early. in /wp-includes/functions.php on line 6121
Et côté navigateur (console), des symptômes typiques :
[Violation] 'requestAnimationFrame' handler took 120ms
[Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event
Uncaught ReferenceError: jQuery is not defined
Où ça apparaît :
- Front-end : page qui “clignote”, LCP élevé, Time To Interactive trop long, défilement saccadé.
- Admin : builder lent, sauvegardes qui moulinent, prévisualisation longue (souvent lié à la même cause : trop d’assets et d’appels AJAX).
- Cron / AJAX : parfois des appels répétés (heartbeat, endpoints REST, admin-ajax) augmentent la charge.
À qui s’adresse ce guide : vous savez ajouter du code (thème enfant ou plugin “mu-plugin”), lire Query Monitor, et vous voulez des optimisations compatibles WordPress 6.9.4+ sans casser Divi 5, Elementor ou Avada. À la fin, vous saurez isoler le goulot (assets, DB, JS), appliquer 3 correctifs code “avant/après”, et valider les gains.
Résumé rapide
- Commencez par mesurer : Query Monitor + DevTools (LCP, TBT) avant de toucher au code.
- Divi 5 devient lent surtout quand vous chargez CSS/JS partout (même sur les pages qui n’en ont pas besoin).
- Deuxième cause fréquente : requêtes DB répétitives (options/autoload, meta queries, shortcodes qui recalculent).
- Troisième cause : scripts tiers (chat, analytics, A/B testing) qui bloquent le thread principal.
- 3 correctifs : enqueues conditionnels, transients + invalidation, defer/delay ciblé (sans toucher aux scripts du builder).
Les symptômes
- Page lente uniquement sur certaines URLs (ex. page d’accueil Divi ultra-modulaire), alors que les articles simples sont corrects.
- LCP > 3s sur mobile, même avec un cache page activé.
- TBT élevé (Total Blocking Time) : la page “répond” tard, scroll qui accroche, clics ignorés.
- Nombre de requêtes très élevé (200+), souvent à cause de scripts tiers + polices + modules.
- HTML livré vite mais rendu lent : serveur OK, mais le navigateur passe son temps en JS.
- Erreurs après ajout de snippets : écran blanc (fatal) ou pages cassées après un “defer” trop agressif.
- Conflit cache/minification : CSS non appliquée, JS “jQuery is not defined”, modules Divi qui ne s’animent plus.
Tableau de diagnostic rapide
| Symptôme | Cause probable | Vérification | Solution |
|---|---|---|---|
| TTFB OK (< 300ms) mais LCP/TBT mauvais | JS tiers + trop d’assets | DevTools > Performance / Lighthouse | Solution 1 + Solution 3 |
| TTFB élevé (> 800ms) même avec cache | Cache mal configuré / pages non cachées / requêtes lourdes | Headers cache + Query Monitor (requêtes) | Solution 2 + vérifier cache serveur |
| Pages uniquement lentes quand connecté | Barre admin, builder, scripts “logged-in” | Test incognito + connecté | Enqueues conditionnels + désactiver modules admin inutiles |
| Builder Divi lent, front acceptable | Plugins admin lourds, Heartbeat, endpoints | Query Monitor (AJAX), Network | Limiter Heartbeat, nettoyer plugins admin |
| Après “defer JS”, animations cassées | Déférer jQuery/Divi scripts | Console “jQuery is not defined” | Solution 3 (liste d’exclusion) |
Pourquoi ça arrive
Version simple : Divi 5 est performant quand il ne fait charger que ce dont la page a besoin. Mais dès que vous empilez des modules, des effets, des polices, des scripts tiers et des plugins “tout-en-un”, vous payez en CSS/JS et en calculs côté navigateur.
Version technique : trois goulots dominent.
- Assets globaux : votre thème/enfant ou vos plugins enqueued des fichiers sur toutes les pages via
wp_enqueue_scripts, parfois sans condition. Même si Divi 5 optimise son propre pipeline, vos ajouts contournent ces optimisations. - Requêtes et calculs répétés : shortcodes, filtres
the_contentet modules qui font desWP_Queryou desget_posts()à chaque hit. Sur un site à fort trafic, le cache page masque partiellement… jusqu’à ce que vous ayez des pages non-cachées (panier, espace membre) ou beaucoup de variations (cookies, géoloc, A/B test). - JavaScript bloquant : scripts de tracking, chat, heatmaps, sliders, etc. Ils ajoutent du travail au thread principal. Le navigateur retarde le rendu, et le score Core Web Vitals s’effondre.
Causes du plus fréquent au plus rare (sur Divi 5) :
- Enqueue “global” (CSS/JS) dans le thème enfant ou un plugin de snippets.
- Minification/concat trop agressive (cache plugin) qui réordonne les dépendances (jQuery en retard, scripts inline avant la lib).
- Requêtes DB répétées + options autoload surdimensionnées.
- Scripts tiers ajoutés “à la main” dans Divi (code module) ou via header/footer plugin.
- Incompatibilité PHP/mémoire (sites encore en PHP 8.0 ou memory_limit trop bas), rare mais réel.
Prérequis avant de commencer
- Sauvegarde complète (fichiers + base). Si vous êtes en production, faites un clone/staging.
- Versions : WordPress 6.9.4, PHP 8.1+ (idéalement 8.2/8.3 si votre hébergeur le propose), Divi 5 à jour.
- Outils :
- Query Monitor pour requêtes, hooks, HTTP API, erreurs PHP.
- Health Check & Troubleshooting pour isoler un conflit sans casser le site public.
- Accès à
wp-config.phppour activer le debug proprement.
Activez un debug exploitable (sur staging si possible) :
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false ); // Évitez d'afficher les notices en front
define( 'SCRIPT_DEBUG', false ); // Laissez à false en prod; true uniquement pour diagnostiquer
Docs officielles utiles : Debug WordPress.
Solution 1 : Nettoyer les CSS/JS chargés inutilement (enqueues conditionnels)
J’ai souvent croisé ce problème sur des sites Divi où le thème enfant charge “site.css” + “site.js” partout, et où ces fichiers embarquent des librairies lourdes (swiper, gsap, fancybox) utilisées sur 2 pages.
Diagnostic
- DevTools > Network : repérez les fichiers CSS/JS “custom” chargés sur une page qui n’en a pas besoin (ex. article simple).
- Query Monitor > Scripts/Styles : identifiez les handles (noms) et l’origine (thème enfant, plugin).
Avant (cassé) : enqueue global
Exemple typique dans functions.php du thème enfant (ou un plugin de snippets) :
<?php
add_action( 'wp_enqueue_scripts', function () {
// Mauvaise pratique : chargé sur toutes les pages, même quand inutile
wp_enqueue_style(
'child-site',
get_stylesheet_directory_uri() . '/assets/site.css',
array(),
'1.0.0'
);
wp_enqueue_script(
'child-site',
get_stylesheet_directory_uri() . '/assets/site.js',
array( 'jquery' ),
'1.0.0',
true
);
}, 10 );
Après (corrigé) : charger uniquement quand nécessaire
Objectif : ne charger vos assets que sur les pages où ils sont utiles. Sur Divi, vous avez souvent des pages identifiables par ID, slug, template, ou présence d’un shortcode/module.
<?php
/**
* Plugin conseillé : placez ce code dans un mu-plugin pour éviter les pertes lors d'une mise à jour.
* Fichier : wp-content/mu-plugins/divi-perf-enqueues.php
*/
add_action( 'wp_enqueue_scripts', function () {
// Ne jamais casser l'admin
if ( is_admin() ) {
return;
}
$should_load = false;
// 1) Exemple : ne charger que sur la page "Accueil" (à adapter)
if ( is_front_page() ) {
$should_load = true;
}
// 2) Exemple : ne charger que sur un template spécifique
if ( is_page_template( 'templates/landing.php' ) ) {
$should_load = true;
}
// 3) Exemple : ne charger que sur une page précise (ID)
if ( is_page( 123 ) ) {
$should_load = true;
}
if ( ! $should_load ) {
return;
}
// Versionnez avec filemtime() pour éviter les caches fantômes après déploiement
$css_path = get_stylesheet_directory() . '/assets/site.css';
$js_path = get_stylesheet_directory() . '/assets/site.js';
wp_enqueue_style(
'child-site',
get_stylesheet_directory_uri() . '/assets/site.css',
array(),
file_exists( $css_path ) ? (string) filemtime( $css_path ) : null
);
wp_enqueue_script(
'child-site',
get_stylesheet_directory_uri() . '/assets/site.js',
array(),
file_exists( $js_path ) ? (string) filemtime( $js_path ) : null,
true
);
}, 20 );
Pourquoi ça accélère réellement
- Moins de bytes à télécharger, surtout sur mobile.
- Moins de CSS à parser (le navigateur passe du temps sur le recalcul de styles).
- Moins de JS à exécuter, donc TBT en baisse.
Explication bloc par bloc
is_admin(): évite de casser l’éditeur/builder.$should_load: centralise la logique. J’ai vu trop de sites avec 10ifdispersés, impossibles à maintenir.filemtime(): vous évite le piège “j’ai corrigé mais le cache sert l’ancienne version”.- Suppression de la dépendance
jquerysi vous n’en avez pas besoin : sur Divi, jQuery est souvent présent, mais ne l’exigez pas inutilement.
Variante utile : désenqueuer un plugin sur certaines pages
Beaucoup de lenteurs viennent de plugins qui chargent partout (formulaires, sliders, maps). Vous pouvez les décharger proprement si vous connaissez les handles.
<?php
add_action( 'wp_enqueue_scripts', function () {
// Exemple : sur les articles, enlever un script inutile (handle à adapter)
if ( is_single() ) {
wp_dequeue_script( 'some-plugin-frontend' );
wp_dequeue_style( 'some-plugin-frontend' );
}
}, 100 ); // Priorité haute pour passer après les enqueues du plugin
Référence officielle : wp_dequeue_script().
Solution 2 : Éviter les requêtes répétitives (transients + cache objet)
Sur Divi 5, les pages “marketing” ont souvent des modules dynamiques (articles en avant, produits, témoignages). Le piège : un shortcode ou un module custom fait une requête DB à chaque affichage, parfois plusieurs fois par page.
Diagnostic
- Query Monitor > Queries : repérez les requêtes répétées (mêmes SELECT, mêmes meta_key).
- Regardez aussi “Caller” : vous verrez vite si ça vient d’un shortcode dans
the_contentou d’un hook global.
Avant (cassé) : shortcode qui requête à chaque hit
Exemple réaliste : un shortcode “derniers articles” injecté dans un module Code Divi.
<?php
add_shortcode( 'latest_posts_cards', function ( $atts ) {
$atts = shortcode_atts(
array(
'count' => 6,
),
$atts,
'latest_posts_cards'
);
$q = new WP_Query(
array(
'post_type' => 'post',
'posts_per_page' => (int) $atts['count'],
'no_found_rows' => true,
)
);
if ( ! $q->have_posts() ) {
return '';
}
ob_start();
echo '<div class="cards">';
while ( $q->have_posts() ) {
$q->the_post();
echo '<a class="card" href="' . esc_url( get_permalink() ) . '">' . esc_html( get_the_title() ) . '</a>';
}
echo '</div>';
wp_reset_postdata();
return (string) ob_get_clean();
} );
Problèmes :
- Chaque affichage = une requête (voire plus si vous ajoutez des metas/terms).
- Si le shortcode est sur plusieurs pages, la charge explose.
- Si vous êtes sur une page non cachée (membre, panier), vous le payez à chaque visite.
Après (corrigé) : transient + invalidation propre
On met en cache le HTML final, et on invalide quand un article est publié/mis à jour. C’est simple, robuste, et compatible avec WordPress 6.9.4.
<?php
/**
* Cache HTML d'un shortcode avec transient.
* Compatible PHP 8.1+.
*/
function bpcab_latest_posts_cards_render( int $count ): string {
$q = new WP_Query(
array(
'post_type' => 'post',
'posts_per_page' => $count,
'no_found_rows' => true,
'ignore_sticky_posts' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
)
);
if ( ! $q->have_posts() ) {
return '';
}
ob_start();
echo '<div class="cards">';
while ( $q->have_posts() ) {
$q->the_post();
echo '<a class="card" href="' . esc_url( get_permalink() ) . '">' . esc_html( get_the_title() ) . '</a>';
}
echo '</div>';
wp_reset_postdata();
return (string) ob_get_clean();
}
add_shortcode( 'latest_posts_cards', function ( $atts ) {
$atts = shortcode_atts(
array(
'count' => 6,
),
$atts,
'latest_posts_cards'
);
$count = max( 1, min( 20, (int) $atts['count'] ) );
// Clé de cache dépendante du paramètre
$cache_key = 'bpcab_latest_posts_cards_' . $count;
$cached = get_transient( $cache_key );
if ( is_string( $cached ) && $cached !== '' ) {
return $cached;
}
$html = bpcab_latest_posts_cards_render( $count );
// TTL raisonnable : 15 minutes (à adapter)
set_transient( $cache_key, $html, 15 * MINUTE_IN_SECONDS );
return $html;
} );
/**
* Invalidation : quand un post est publié/mis à jour/supprimé.
* On supprime plusieurs variantes (count 1..20) pour rester simple.
*/
function bpcab_latest_posts_cards_purge_cache(): void {
for ( $i = 1; $i <= 20; $i++ ) {
delete_transient( 'bpcab_latest_posts_cards_' . $i );
}
}
add_action( 'save_post_post', function ( $post_id, $post, $update ) {
// Évitez les autosaves/révisions
if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
return;
}
bpcab_latest_posts_cards_purge_cache();
}, 10, 3 );
add_action( 'deleted_post', function ( $post_id ) {
if ( get_post_type( $post_id ) === 'post' ) {
bpcab_latest_posts_cards_purge_cache();
}
}, 10, 1 );
Pourquoi ça corrige le problème
- Vous supprimez des requêtes sur la majorité des hits (surtout avec cache objet Redis/Memcached).
- Vous évitez le recalcul HTML dans
the_content, qui est un point chaud sur Divi (beaucoup de filtres). - Vous limitez les caches meta/terms via
update_post_meta_cacheetupdate_post_term_cachequand vous n’en avez pas besoin.
Notes performance et compatibilité
- Les transients sont stockés en DB sans cache objet, et en mémoire avec Redis/Memcached. Les deux sont OK, mais le gain est bien meilleur avec un cache objet persistant.
- Doc officielle : Transients API.
- Évitez de mettre un TTL “1 jour” sans invalidation : vous verrez des contenus périmés et vous finirez par “vider tous les caches” en panique.
Solution 3 : Retarder le JavaScript tiers (defer/delay) sans casser Divi 5
Le scénario classique : vous activez une option “Delay JS” dans un plugin de cache, et Divi (ou un module) casse. Ensuite vous désactivez l’option, et vous perdez un gain énorme. La bonne approche consiste à déférer uniquement le tiers, et à exclure les scripts critiques (jQuery, scripts du thème/builder, scripts inline dépendants).
Diagnostic
- DevTools > Performance : repérez les longues tâches (long tasks) et le JS qui bloque.
- DevTools > Network : identifiez les domaines tiers (ex.
connect.facebook.net,www.googletagmanager.com, chat, etc.).
Avant (cassé) : defer global sur tous les scripts
Snippet dangereux que je vois encore circuler (souvent copié d’un vieux tutoriel) :
<?php
add_filter( 'script_loader_tag', function ( $tag ) {
// Mauvaise pratique : defer sur absolument tout
return str_replace( '<script ', '<script defer ', $tag );
} );
Résultats typiques : Uncaught ReferenceError: jQuery is not defined, modules Divi qui ne s’initialisent pas, sliders figés.
Après (corrigé) : defer ciblé + liste d’exclusion
On applique defer seulement aux scripts non-critiques, et on exclut explicitement les handles sensibles. Le point clé : on ne devine pas les handles Divi internes (ils peuvent évoluer). On exclut plutôt par dépendances et par “familles” (jQuery + scripts marqués comme critiques), et on limite au tiers que vous contrôlez (vos scripts + quelques plugins).
<?php
/**
* Defer ciblé des scripts front.
* Objectif : réduire le JS bloquant sans casser Divi 5.
*
* Placez ce code en mu-plugin et testez sur staging.
*/
add_filter( 'script_loader_tag', function ( $tag, $handle, $src ) {
if ( is_admin() ) {
return $tag;
}
// 1) Exclusions strictes : ne touchez pas à jQuery ni aux scripts "core"
$excluded_handles = array(
'jquery',
'jquery-core',
'jquery-migrate',
);
if ( in_array( $handle, $excluded_handles, true ) ) {
return $tag;
}
// 2) Exclure les scripts chargés dans l'en-tête (souvent critiques)
// Si un script n'est pas en footer, on évite d'y toucher par défaut.
// (On ne peut pas toujours détecter "in_footer" ici de façon fiable selon les plugins.)
// Stratégie : n'appliquer defer qu'à une allowlist.
$allowed_handles = array(
'child-site', // Votre JS custom
'contact-form-7', // Exemple : à adapter
'wpforms', // Exemple : à adapter
'gtm4wp', // Exemple : à adapter
);
if ( ! in_array( $handle, $allowed_handles, true ) ) {
return $tag;
}
// 3) N'ajoutez pas defer si déjà présent
if ( str_contains( $tag, ' defer' ) ) {
return $tag;
}
// Ajout de defer
return str_replace( '<script ', '<script defer ', $tag );
}, 10, 3 );
Option “delay” (plus agressive) : uniquement pour scripts tiers identifiés
Quand le vrai problème vient d’un script tiers (chat/heatmap), defer ne suffit pas toujours. Vous pouvez retarder leur chargement après interaction. C’est plus risqué (UX, tracking), mais efficace.
Exemple minimaliste : on n’injecte un script tiers qu’après le premier scroll/clic. Je le fais surtout pour des widgets de chat.
<?php
/**
* Injecte un loader JS "delay" en footer.
* Ajustez la liste de scripts tiers selon vos besoins.
*/
add_action( 'wp_footer', function () {
if ( is_admin() ) {
return;
}
?>
<script>
(function() {
"use strict";
var loaded = false;
function loadThirdParty() {
if (loaded) return;
loaded = true;
// Exemple : charger un script tiers (URL à adapter)
var s = document.createElement("script");
s.src = "https://example-cdn.invalid/chat-widget.js";
s.async = true;
document.head.appendChild(s);
}
// Déclencheurs : interaction utilisateur
window.addEventListener("scroll", loadThirdParty, { passive: true, once: true });
window.addEventListener("click", loadThirdParty, { passive: true, once: true });
window.addEventListener("keydown", loadThirdParty, { passive: true, once: true });
// Fallback : charge au bout de 8s si aucune interaction
window.setTimeout(loadThirdParty, 8000);
})();
</script>
<?php
}, 100 );
Risques : vous pouvez perdre des événements analytics “pageview” si vous retardez trop. Testez avec votre outil (GA4, Matomo, Pixel) et documentez ce choix.
Doc officielle sur le chargement des scripts : wp_enqueue_script() et filtre script_loader_tag.
Vérifications après correction
- Mesure avant/après :
- Lighthouse (mobile) : LCP, TBT, CLS.
- DevTools > Network : nombre de requêtes, poids total transféré.
- Query Monitor : nombre de requêtes DB, temps total, requêtes lentes.
- Tests fonctionnels Divi 5 :
- Menus, ancres, sliders, accordéons, formulaires.
- Pages avec modules dynamiques (blog, shop, testimonials).
- Test connecté vs déconnecté : Divi et certains plugins chargent plus quand vous êtes loggé.
- Cache : videz cache plugin + cache serveur (si vous avez) + cache navigateur. J’ai vu des gens “valider” une régression parce qu’ils testaient une vieille ressource en cache.
Si ça ne marche toujours pas
- Isoler un conflit avec Health Check (mode Troubleshooting) : désactivez tous les plugins sauf Divi/Divi Builder, puis réactivez un par un.
- Vérifier les erreurs PHP dans
wp-content/debug.log. Une pluie de notices peut ralentir (surtout si log sur disque lent). - Contrôler la mémoire PHP : si vous frôlez la limite, vous aurez du swapping/GC. Vérifiez
WP_MEMORY_LIMITet la limite côté hébergeur. - Regarder les options autoload : quand
autoloaddevient énorme, chaque requête charge trop de données. Query Monitor peut aider, sinon inspection DB (avancé). - Désactiver temporairement minification/concat (plugin de cache) : si le site redevient stable, le problème est l’ordre des scripts. Réactivez ensuite en excluant les handles Divi/jQuery.
- Console navigateur : une seule erreur JS peut empêcher l’initialisation de modules (ce qui ressemble à un “site lent” alors que c’est un script qui boucle).
- Tester sans CDN (temporairement) : un CDN mal configuré peut ajouter de la latence et des misses cache.
- Rewrites : si vous avez des 404 sur assets, régénérez les permaliens (réécriture) et vérifiez les règles serveur.
Commandes WP-CLI utiles (si vous avez l’accès)
# Vérifier l'environnement
wp core version
wp php version
wp plugin list --status=active
wp theme list
# Vider certains caches (selon votre stack)
wp cache flush
# Repérer des options autoload (avancé, à manipuler avec prudence)
wp db query "SELECT SUM(LENGTH(option_value)) AS autoload_bytes FROM wp_options WHERE autoload='yes';"
WP-CLI : documentation officielle.
Pièges et erreurs courantes
| Symptôme | Cause probable | Solution recommandée |
|---|---|---|
| Écran blanc après ajout du snippet | Code copié au mauvais endroit / point-virgule manquant | Tester sur staging, activer WP_DEBUG_LOG, corriger la syntaxe |
jQuery is not defined |
Defer appliqué à jQuery ou ordre des scripts cassé par minification | Exclure jquery/jquery-core, désactiver concat, retester |
| Le snippet “ne marche pas” | Cache page/CDN sert l’ancienne version | Versionner avec filemtime(), purger cache plugin + CDN |
| Optimisation OK en local, lente en prod | Scripts tiers, latence réseau, cache objet absent | Profiler en prod (sans impacter), activer Redis/Memcached si possible |
| Hooks non exécutés | Snippet placé dans un plugin désactivé / conflit avec un plugin de snippets | Préférer un mu-plugin, vérifier l’ordre de chargement |
| CSS/JS non chargés | Mauvais get_stylesheet_directory_uri() vs get_template_directory_uri() |
En thème enfant, utiliser get_stylesheet_* |
| Régression sur Elementor/Avada | Désenqueuer un handle partagé ou trop global | Conditionner par page/template, éviter les règles “sitewide” |
Erreurs que je vois souvent (et qui coûtent cher)
- Copier un snippet “defer tout” trouvé sur un forum : ça casse tôt ou tard.
- Mettre le code dans le mauvais fichier (ex.
functions.phpdu thème parent Divi). À la prochaine mise à jour, tout saute. - Oublier la priorité : pour
wp_dequeue_script, il faut souvent une priorité haute (ex. 100). - Confondre action et filtre :
script_loader_tagest un filtre, pas une action. - Tester directement en production sans rollback. Sur un site Divi, une erreur JS peut impacter toutes les pages.
Variante / alternative
Méthode sans code (plugins)
- Un plugin de cache/perf qui gère exclusions par handle (minification, delay JS) peut suffire si vous prenez le temps de configurer les exclusions Divi. Le piège, c’est le “one-click optimize” : sur Divi, ça casse souvent.
- Pour la DB, un cache objet persistant (Redis/Memcached) apporte un gain net sur les pages non-cachées.
Méthode plus avancée (développeurs)
- Profiler PHP (APM) : Sentry, New Relic, Datadog. Vous verrez immédiatement si la lenteur est DB, HTTP API, ou CPU.
- Remplacer certains shortcodes par des blocs statiques ou des patterns, quand le contenu n’a pas besoin d’être recalculé à chaque hit.
- Découper le JS custom : un bundle par type de page, chargé conditionnellement (Solution 1), plutôt qu’un
site.jsmonolithique.
Éviter ce problème à l’avenir
- Adoptez une règle simple : aucun CSS/JS custom “global” sans justification. Chargez par page/template ou par fonctionnalité.
- Cachez ce qui est coûteux : shortcodes et requêtes doivent avoir une stratégie de cache (transient + invalidation).
- Évitez les dépendances invisibles : si votre JS dépend de jQuery, déclarez-le explicitement. Si possible, migrez vers du JS vanilla pour réduire les contraintes d’ordre.
- Surveillez les scripts tiers : chaque widget “gratuit” ajoute du coût. J’ai vu des pages avec 12 tags marketing ; aucune optimisation WordPress ne compense ça.
- Gardez un changelog interne : quand vous activez “delay JS”, notez les exclusions, sinon vous perdrez des heures au prochain incident.
Références utiles côté WordPress :
- Bonnes pratiques enqueue : Including CSS & JavaScript
- API Transients : Transients
- Hooks scripts : script_loader_tag
Ressources
- Debug WordPress (WP_DEBUG, logs)
- developer.wordpress.org — Including CSS and JavaScript
- developer.wordpress.org — Transients API
- developer.wordpress.org — Filtre script_loader_tag
- Query Monitor (plugin)
- Health Check & Troubleshooting (plugin)
- WordPress Core Trac (recherche de tickets perf)
- GitHub — wordpress-develop (code source)
- PHP.net — OPcache (impact direct sur perf)
Questions fréquentes
Divi 5 est-il forcément plus lent qu’un thème bloc ?
Non. Sur des pages simples, Divi 5 peut être très correct. La différence se fait surtout sur les pages très modulaires et sur la quantité de scripts tiers. Le vrai facteur, c’est ce que vous chargez et exécutez sur chaque page.
Où placer le code : thème enfant, plugin, mu-plugin ?
Pour des optimisations “infrastructure” (enqueues, defer, cache), je recommande un mu-plugin. Vous évitez les pertes lors d’une mise à jour Divi ou d’un changement de thème.
Est-ce compatible avec Elementor ou Avada ?
Oui si vous restez sur des conditions par page/template et une allowlist de handles. Le danger, c’est le snippet “defer tout” ou les wp_dequeue_* trop globaux, qui peuvent retirer des assets nécessaires à un autre builder.
Pourquoi Query Monitor montre moins de requêtes mais la page reste lente ?
Parce que le goulot est probablement côté navigateur (JS/CSS) ou réseau (scripts tiers). Vérifiez TBT, les long tasks, et le poids total transféré.
Le cache page ne suffit-il pas ?
Le cache page aide surtout le TTFB. Si votre LCP/TBT est mauvais, c’est souvent du CSS/JS trop lourd ou mal chargé. D’où l’intérêt des enqueues conditionnels et du defer ciblé.
Dois-je activer OPcache ?
Oui, si votre hébergeur le permet. OPcache réduit fortement le coût CPU PHP. Référence : PHP OPcache.
Comment savoir quels handles exclure du defer ?
Commencez par exclure jquery, jquery-core, puis ajoutez au fur et à mesure les scripts qui cassent. Utilisez Query Monitor (onglet Scripts) pour voir les handles exacts.
Le transient va-t-il poser des problèmes de contenu périmé ?
Pas si vous invalidez correctement lors des mises à jour (ex. save_post). Sans invalidation, oui, vous finirez avec du contenu incohérent.
Est-ce que “delay JS” est mauvais pour le SEO ?
Ça dépend de ce que vous retardez. Retarder un chat n’a généralement pas d’impact SEO. Retarder un script qui injecte du contenu visible peut poser problème. Gardez les scripts critiques immédiats, et retardez le tiers non essentiel.
Je vois des lenteurs uniquement quand je suis connecté, c’est normal ?
Souvent oui : barre admin, scripts d’édition, plugins qui chargent des assets “logged-in”. Testez toujours en navigation privée pour mesurer l’expérience visiteur.