Les mises à jour WP Rocket, en général, ça se passe bien. Et c’est justement ça le piège. Quand tu actives « Delay JavaScript execution », tu acceptes un contrat implicite : WP Rocket va toucher à la façon dont tes scripts sont injectés, typés, et déclenchés. Tant que la mécanique colle aux attentes des libs (et des scripts maison), c’est magique pour les Core Web Vitals. Le jour où un détail change, tu peux te retrouver avec un site qui a l’air « normal »… mais où un formulaire ne part plus, un checkout ne valide plus, ou un tracking ne remonte plus. Sans stacktrace. Sans gros message rouge.
WP Rocket 3.20.6 a justement un changelog qui sent ce genre de zone sensible, avec des ajustements autour des attributs/type des scripts retardés, puis un hotfix 3.20.6.1 pour une compatibilité Delay JS avec une ancienne version du script. Traduction terrain : si tu es en auto-update, tu peux prendre une régression front qui ressemble à « tout marche »… jusqu’à ce que tu regardes les conversions.
Pourquoi un changement « d’attribut de script » peut plier un site
Delay JS fonctionne en empêchant certains scripts de s’exécuter au chargement, puis en les rejouant après une interaction ou un trigger. Pour faire ça, le plugin doit modifier les balises <script> dans le HTML : il joue sur le type, ajoute des attributs de data, déplace la ressource dans un attribut, et s’appuie sur un loader côté navigateur pour « relancer » tout ça au bon moment.
Le problème, c’est que beaucoup d’outils s’attendent à une balise <script> très standard. Certains scripts scrutent le DOM pour retrouver leur propre tag, d’autres attachent des handlers « au chargement », d’autres encore se branchent sur des événements qui n’arrivent plus dans le même ordre. Tu peux aussi avoir des bouts de code qui marchent par hasard uniquement parce que « le script X arrivait avant Y ». Retarder X, ou modifier sa balise, et tu changes l’ordre du monde.
Et là où c’est vicieux, c’est que l’UI ne s’écroule pas forcément. Tu peux scroller, cliquer, voir le header, et te dire que c’est OK. Sauf que les actions business (ajout panier, paiement, envoi de lead, ouverture de modale de consentement, tracking e-commerce) sont souvent les premières à prendre cher.
Sponsorisé par Le Scribouillard
Besoin de contenu optimisé SEO ?
Utilisez la meilleure plateforme française de création de contenu assistée par IA ! Et générez des articles pour moins de 1€ !
Le bug silencieux typique : tout a l’air OK, mais la page ne « finit » jamais
Sur un site WordPress classique, les régressions Delay JS ressemblent rarement à un gros crash. Ça ressemble plutôt à un état incomplet. Un bouton qui ne répond qu’au deuxième clic. Une validation de formulaire qui tourne. Un menu qui s’ouvre mais ne se referme plus. Une modale qui devrait apparaître (login, panier, âge légal, consentement) et qui ne vient jamais.
Côté tracking, c’est encore plus sournois. La pageview remonte, donc tout le monde se calme. Mais les events importants (add_to_cart, begin_checkout, submit_form, purchase, ou l’équivalent maison) ne partent plus parce que le script qui pousse dans dataLayer n’a jamais été exécuté. Et comme c’est « juste » du JS retardé, tu n’as pas forcément d’erreur en console. Tu as juste… du silence.
Mon protocole d’upgrade WP Rocket quand Delay JS est activé
Si ton site a un enjeu business, la règle c’est simple : pas d’upgrade WP Rocket en prod « parce que c’est un plugin de perf ». Delay JS, c’est de la logique applicative déguisée. Donc je traite ça comme une mise à jour qui peut casser des parcours.
Je commence par figer un environnement de préprod qui ressemble vraiment à la prod. Pas une page d’accueil statique. Le même thème, les mêmes plugins, les mêmes tags, et idéalement une copie de contenu. Je purge les caches (WP Rocket, objet si tu en as, CDN) pour éviter de valider un résultat qui n’est pas représentatif. Et j’évite les tests « en étant loggé admin », parce que c’est souvent un autre monde : scripts différents, cache bypass, et comportement différent.
Ensuite je me crée 5 à 8 pages de référence qui couvrent les endroits où Delay JS fait mal quand ça casse. Une page « contenu » (un article), une page avec un formulaire (contact ou lead), une page liste (catégorie, recherche interne), une page produit si e-commerce, le panier, le checkout, et une page avec un composant JS un peu riche (slider, filtre, carte, prise de RDV). L’idée n’est pas de cocher une checklist, c’est d’avoir un petit set stable que tu rejoues à chaque upgrade.
Enfin je fais un test comparatif avant/après mise à jour en regardant trois choses, toujours dans cet ordre. D’abord le comportement utilisateur (clics, saisies, submit, paiement en sandbox si possible). Ensuite la console et le réseau (erreurs, scripts jamais chargés, appels XHR manquants). Et seulement après je regarde les métriques perf. Un site très rapide qui ne vend plus, c’est juste un incident bien optimisé.
Identifier le script qui ne se déclenche plus (sans jouer à deviner)
Quand tu suspectes Delay JS, ton but n’est pas de « désactiver Delay JS » pour voir si ça remarche. Ça, tu le sais déjà. Ton but, c’est d’isoler le ou les scripts qui n’aiment pas être retardés, pour les exclure proprement. Sinon tu vas finir par exclure la moitié de ton site et perdre l’intérêt de la feature.
Le réflexe qui fait gagner du temps, c’est d’inspecter directement ce que la page contient comme scripts retardés, et de repérer ceux qui sont critiques pour le parcours que tu testes (checkout, validation, widgets). Ouvre DevTools, va sur la page concernée, et liste les scripts dont le type ou les attributs ont été modifiés.
// À coller dans la console DevTools sur une page qui bugge
const delayed = [...document.scripts].filter(s => {
const t = (s.type || '').toLowerCase();
return t.includes('rocket') || s.dataset.rocketType || s.dataset.rocketSrc;
});
console.table(delayed.map(s => ({
src: s.src || '(inline)',
type: s.type || '(empty)',
rocketType: s.dataset.rocketType || '',
rocketSrc: s.dataset.rocketSrc || '',
inlinePreview: (s.src ? '' : (s.textContent || '').trim().slice(0, 120))
})));À partir de là, tu ne cherches pas « le script WP Rocket ». Tu cherches « ce qui manque » au moment où l’action devrait se produire. Exemple concret : tu cliques sur « Payer », rien ne se passe. Regarde dans l’onglet Network si une requête XHR/Fetch part. Si rien ne part, c’est souvent un handler d’événement qui n’a jamais été attaché, donc un script non exécuté. Si une requête part mais la réponse n’est pas traitée, c’est parfois un script d’UI (validation, rendu, composant) qui n’a pas repris la main après le retour API.
Autre angle très efficace quand le souci est « tracking / consent / tags ». Tu instrumentes dataLayer.push pour voir si des events arrivent vraiment quand tu cliques, et si le flux s’arrête après une update.
// Sur un site avec GTM/dataLayer
window.dataLayer = window.dataLayer || [];
const _push = window.dataLayer.push;
window.dataLayer.push = function () {
console.log('[dataLayer.push]', ...arguments);
return _push.apply(window.dataLayer, arguments);
};Si avant update tu vois passer tes events (view_item, add_to_cart, submit_form…) et qu’après update c’est mort, tu as un indicateur clair : ce n’est pas « Google qui déconne », ce n’est pas « GA4 en retard ». C’est ton JS qui ne s’exécute plus au bon moment. Et donc, très probablement, un script que Delay JS retarde alors qu’il ne devrait pas.
Choisir les exclusions Delay JS sans tuer l’objectif perf
Le piège classique, c’est d’exclure « tout ce qui ressemble à un truc important ». En pratique, tu peux finir par exclure GTM + le bundle principal + le script du thème + 12 scripts de widgets, et tu reviens à la perf d’avant, avec juste une config plus fragile.
Ce que je fais à la place, c’est d’exclure par intention. Un script de paiement, un script de formulaire, un script de consentement, un script qui gère la navigation critique du site, ça a le droit de ne pas être retardé. À l’inverse, un chat, une heatmap, un A/B test non essentiel, un widget social, ça peut attendre. Et si un outil marketing « doit absolument se déclencher avant toute interaction », je le challenge un peu. Souvent c’est juste une habitude, pas une contrainte technique.
Ensuite je préfère des exclusions chirurgicales. Quand tu peux exclure une URL précise de script plutôt qu’un motif trop large, fais-le. Quand tu peux exclure un inline script minimal parce qu’il initialise un composant vital, fais-le. L’idée, c’est de garder Delay JS comme une optimisation de surface, pas comme une règle qui reconfigure toute ton app. Plus tu exclus large, plus tu te rapproches d’un setup instable où chaque update te force à retoucher la config.
Dernier point : pense « ordre de chargement ». Certains bugs n’arrivent pas parce qu’un script est retardé, mais parce qu’il est rejoué après un autre, donc dans un ordre différent. Si tu as des dépendances implicites entre scripts, tu peux soit les rendre explicites (mieux), soit exclure le bon script pour restaurer un ordre stable (parfois nécessaire sur un WordPress un peu chargé).
Le vrai fix, c’est d’arrêter les auto-updates en aveugle
Je suis pour les mises à jour, vraiment. Mais WP Rocket avec Delay JS activé, sur un site qui vend, c’est « update managée ». Pas « update automatique à 3h du matin et on verra ». Le coût d’un bug silencieux est trop élevé, parce que tu ne le vois pas tout de suite. Tu le vois au mieux sur les tickets, au pire sur le chiffre.
Concrètement, je garde un chemin de rollback simple (savoir revenir à la version précédente rapidement), je note la config WP Rocket avant changement, et je fais en sorte d’avoir un signal post-release. Ça peut être un RUM, ça peut être un monitoring de parcours (un faux checkout, un submit de formulaire en staging branché sur une inbox de test), ou au minimum une vérif des events clés sur une fenêtre courte après mise en prod.
Et si tu dois absolument rester en auto-update, au moins ne le fais pas sans garde-fou. Parce que ce genre de modification « attribut/type de script + hotfix compat loader » est exactement le type de truc qui ne te donne pas une erreur visible, mais qui te casse l’exécution d’un bout de JS au mauvais endroit. Et c’est comme ça qu’on se retrouve à « avoir un site rapide » qui a perdu une semaine de tracking ou un taux de conversion, sans comprendre pourquoi.