vendredi 25 septembre 2026

À propos

Contact

Performance

Un bloc dynamique dont le render_callback plombe le rendu de la page

Un bloc Gutenberg dynamique qui interroge une API externe à chaque rendu ralentit toute la page. Diagnostic avec Query Monitor et correctif par transient court.

Par Clément Hadrot • 22 juillet 2022 • 4 min de lecture • Aucun commentaire
Un bloc dynamique dont le render_callback plombe le rendu de la page

Un site météo local avait développé un bloc Gutenberg personnalisé affichant la météo du jour en en-tête de chaque article de blog, en interrogeant une API météo externe. Le bloc fonctionnait très bien en test, avec un seul article affiché à la fois. En production, sur une page de liste affichant dix articles, chacun avec sa propre instance du bloc, le temps de chargement de la page a commencé à dépasser cinq secondes par moments, en particulier lorsque l’API externe répondait plus lentement que d’habitude.

La particularité des blocs dynamiques, par opposition aux blocs statiques dont le rendu est figé au moment de la publication, est justement leur exécution à chaque affichage de la page côté serveur, via une fonction PHP enregistrée comme render_callback. C’est cette caractéristique qui, mal utilisée, a transformé un simple affichage météo en goulet d’étranglement.

Diagnostic avec Query Monitor

Query Monitor ne se limite pas aux requêtes SQL : son panneau « HTTP API Calls » liste chaque appel réseau sortant effectué pendant la génération de la page, avec son temps de réponse individuel. Sur la page de liste incriminée, dix appels distincts vers l’API météo apparaissaient, un par instance du bloc, avec des temps de réponse individuels variant entre 200 millisecondes et plus d’une seconde selon la charge du service tiers à cet instant.

Le code du bloc, simplifié, ressemblait à ceci :

register_block_type( 'monsite/meteo-du-jour', array(
    'render_callback' => function ( $attributs ) {
        $reponse = wp_remote_get( 'https://api.meteo-externe.fr/v1/actuelle?ville=' . $attributs['ville'] );
        $donnees = json_decode( wp_remote_retrieve_body( $reponse ), true );
        return '<p>Météo à ' . esc_html( $attributs['ville'] ) . ' : ' . esc_html( $donnees['temperature'] ) . ' °C</p>';
    },
) );

Chaque affichage de la page relançait cet appel réseau, sans aucune mise en cache, ce qui explique pourquoi le temps de génération de la page variait fortement d’un chargement à l’autre, selon la disponibilité du service météo à cet instant précis.

L'essentiel à retenir : Un render_callback s'exécute à chaque affichage de page, pas à la publication ; Un appel réseau externe dans ce callback bloque tout le rendu de la page ; Un transient court amortit le coût sans figer le contenu trop longtemps

Le correctif par transient

La météo d’une ville donnée ne change pas d’une seconde à l’autre, ce qui rendait un cache de quelques minutes largement acceptable pour l’usage réel. Le correctif a consisté à envelopper l’appel réseau dans un transient, avec une durée de quinze minutes, jugée pertinente pour ce cas d’usage :

register_block_type( 'monsite/meteo-du-jour', array(
    'render_callback' => function ( $attributs ) {
        $cle_transient = 'meteo_' . sanitize_key( $attributs['ville'] );
        $donnees       = get_transient( $cle_transient );

        if ( false === $donnees ) {
            $reponse = wp_remote_get( 'https://api.meteo-externe.fr/v1/actuelle?ville=' . $attributs['ville'], array(
                'timeout' => 3,
            ) );

            if ( ! is_wp_error( $reponse ) ) {
                $donnees = json_decode( wp_remote_retrieve_body( $reponse ), true );
                set_transient( $cle_transient, $donnees, 15 * MINUTE_IN_SECONDS );
            }
        }

        if ( ! $donnees ) {
            return '';
        }

        return '<p>Météo à ' . esc_html( $attributs['ville'] ) . ' : ' . esc_html( $donnees['temperature'] ) . ' °C</p>';
    },
) );

Deux détails complémentaires ont été ajoutés : un timeout explicite de trois secondes sur l’appel réseau, pour éviter qu’une API externe en difficulté ne bloque le rendu de la page indéfiniment, et un retour silencieux, sans erreur visible, si l’appel échoue malgré tout.

Le résultat après correctif

Avec la clé de transient construite par ville, toutes les instances du bloc pour une même ville partagent désormais le même cache, ce qui réduit également le nombre d’appels réseau effectifs vers l’API météo, un bénéfice apprécié par le fournisseur de l’API lui-même dont les quotas d’appels commençaient à être sollicités. Le temps de génération de la page de liste est redescendu à moins de 400 millisecondes de façon stable.

  • Ne jamais placer un appel réseau externe sans cache dans un render_callback appelé potentiellement plusieurs fois par page.
  • Toujours fixer un timeout explicite sur les appels via wp_remote_get().
  • Adapter la durée du transient à la fraîcheur réellement nécessaire de la donnée, pas par défaut à une heure.

En résumé

Un bloc dynamique reste un bloc de code PHP exécuté à chaque affichage, avec les mêmes règles de prudence que n’importe quelle autre partie de WordPress vis-à-vis des appels réseau. Ce cas ne traite pas les blocs statiques, dont le rendu est figé à la publication, ni la logique de rendu gérée via un script JavaScript propre au bloc côté client, qui répond à des règles de performance différentes.

Partager :

À propos de l'auteur

Clément Hadrot

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

Voir tous ses articles

Dans la même veine

À lire aussi