Le WordPress d'aujourd'hui, décodé pour les développeurs

Blocs Gutenberg

Compatibilité W3 Total Cache et un bloc dynamique : rendu qui reste figé

Un bloc affichant le nombre de places restantes reste bloqué sur une valeur périmée après activation du cache de page. La règle d'exclusion à ajouter tient en une ligne.

Par WordPress Développement • 2 mai 2023 • 5 min de lecture • Aucun commentaire
Compatibilité W3 Total Cache et un bloc dynamique : rendu qui reste figé

« Plus que 2 places disponibles » affichait un bloc de compte à rebours d’inscription à un webinaire, alors que l’événement était déjà complet depuis la veille. Le symptôme est apparu le jour même de l’activation du cache de page de W3 Total Cache sur un site jusque-là servi sans cache, en prévision d’un pic de trafic annoncé sur les réseaux sociaux.

Le bloc en question est un bloc dynamique standard, avec un render_callback PHP qui interroge une table de réservations à chaque affichage. Fonctionnellement irréprochable sans cache, il devient un piège dès qu’une couche de cache de page s’intercale entre la requête et le rendu final envoyé au navigateur.

Pourquoi le cache de page ignore la logique du bloc

Le cache de page de W3 Total Cache fonctionne en amont de WordPress : une fois une page générée, son HTML complet est stocké tel quel (sur disque, en mémoire, ou via un CDN) et resservi directement aux visiteurs suivants, sans jamais réexécuter PHP. Le render_callback du bloc s’exécute donc une seule fois, au moment de la mise en cache initiale, puis plus jamais avant l’expiration ou la purge du cache.

C’est un comportement voulu et documenté du plugin : le cache de page ne sait rien de la nature « dynamique » d’un bloc Gutenberg, il ne voit qu’une page HTML à mettre en cache dans son ensemble. Le problème ne vient donc pas d’un bug de W3 Total Cache, mais d’une incompatibilité de principe entre cache de page complet et contenu qui doit changer à chaque requête.

La solution : isoler le fragment avec mfunc

W3 Total Cache propose depuis longtemps un mécanisme dédié à ce cas précis : les balises de commentaire mfunc, qui indiquent au moteur de cache de ne pas figer le contenu qu’elles entourent, et de le réévaluer dynamiquement à chaque affichage même quand le reste de la page est servi depuis le cache.

L'essentiel à retenir : Le cache de page fige tout le HTML, y compris le bloc dynamique ; Les balises mfunc isolent la portion réellement dynamique ; Le fragment cache évite de désactiver le cache complet
function acme_render_places_restantes( $attributes ) {
    ob_start();
    ?>
    <!--mfunc acme_get_places_restantes-->
    <p class="places-restantes">
        Plus que <?php echo esc_html( acme_get_places_restantes() ); ?> places disponibles
    </p>
    <!--/mfunc-->
    <?php
    return ob_get_clean();
}

Le fonctionnement est particulier : W3 Total Cache repère la balise mfunc au moment de la mise en cache initiale, remplace la portion correspondante par un appel de fonction PHP réinjecté à chaque service de la page depuis le cache. La fonction citée en paramètre de la balise (ici acme_get_places_restantes) doit être une fonction globale, appelable sans contexte, ce qui impose parfois de sortir la logique de calcul hors de la classe du bloc.

Activer le fragment cache plutôt que tout désactiver

La première réaction — désactiver totalement le cache de page sur les pages contenant ce bloc — est contre-productive : elle prive tout le reste de la page (menu, pied de page, contenu éditorial) du bénéfice du cache, pour une seule portion réellement volatile. L’onglet Performance → Cache de page → Réglages avancés de W3 Total Cache permet, en complément des balises mfunc, d’activer le fragment caching avec un objet de cache dédié (Redis ou Memcached recommandé plutôt que le disque), ce qui limite la fréquence de recalcul du fragment sans revenir à un recalcul à chaque requête.

  • Repérer chaque bloc dynamique dont la donnée change plus vite que la durée de vie du cache de page.
  • Entourer uniquement la portion concernée avec mfunc, jamais le bloc entier si une partie est statique.
  • Vérifier que la fonction citée dans mfunc reste légère : elle s’exécute à chaque affichage, cache ou non.
  • Purger le cache de page après chaque déploiement touchant à la structure du bloc, pas seulement à son contenu.

Un piège annexe : le cache d’objets et les transients

Sur ce même projet, une seconde couche de cache — l’object cache Redis, activé en parallèle — masquait une partie du problème : la fonction acme_get_places_restantes() utilisait un transient de dix minutes, ce qui rallongeait encore la fenêtre d’incohérence entre la réalité des réservations et l’affichage du bloc. Réduire la durée du transient à trente secondes, combiné à la balise mfunc, a suffi à rendre l’affichage acceptable sans revenir à une exécution non cachée à chaque requête.

Avant d’accuser le plugin de cache, je vérifie toujours l’empilement complet des couches en jeu : cache de page, cache d’objets, et transients internes au code peuvent se cumuler sans qu’aucune ne soit individuellement responsable du symptôme observé.

En résumé

Un bloc dynamique n’est pas incompatible avec le cache de page, à condition d’identifier précisément la portion réellement volatile et de l’isoler avec les mécanismes prévus à cet effet, comme les balises mfunc de W3 Total Cache. La tentation de tout désactiver ou de tout laisser en cache complet mène systématiquement soit à une perte de performance, soit à un affichage périmé — la bonne réponse se trouve toujours entre les deux.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi