200 000 articles publiés, un rythme de publication d’une trentaine de nouvelles par jour, et un bloc « articles à la une » qui mettait plus de six secondes à s’afficher dans l’éditeur à chaque ouverture d’une page d’accueil. Ce chiffre, mesuré avec l’onglet Performance du navigateur, a servi de point de départ à une optimisation qui a fini par diviser ce temps par plus de quinze.
Le bloc, en apparence simple, listait les cinq derniers articles d’une catégorie donnée, triés par date, avec une image mise en avant et un extrait. Sur un volume de contenu aussi élevé, chaque détail de la requête sous-jacente pesait bien plus lourd que sur un site classique.
Premier diagnostic : une requête WP_Query trop gourmande
La requête initiale demandait bien plus de données que nécessaire pour un simple aperçu de cinq articles :
$articles = new WP_Query( array(
'category_name' => $attributes['categorie'],
'posts_per_page' => 5,
'orderby' => 'date',
'order' => 'DESC',
) );
Sans restriction explicite, WP_Query charge par défaut l’intégralité des métadonnées et de la taxonomie associées à chaque article, y compris celles qui ne servent jamais à l’affichage du bloc. Sur un site avec des dizaines de champs personnalisés par article (auteur, source, niveau de vérification, tags internes), ce chargement superflu représentait l’essentiel du temps de requête mesuré.

Réduire la requête au strict nécessaire
Deux paramètres ont changé la donne : désactiver le comptage total des résultats, inutile pour un simple top 5, et limiter les champs récupérés :
$articles = new WP_Query( array(
'category_name' => $attributes['categorie'],
'posts_per_page' => 5,
'orderby' => 'date',
'order' => 'DESC',
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'fields' => 'ids',
) );
Le paramètre fields => 'ids' ne récupère que les identifiants, à charge pour le code d’aller chercher ensuite uniquement les données réellement affichées (titre, image, extrait) via get_post(), appelé seulement pour les cinq résultats retenus plutôt que pour un jeu de données bien plus large en amont.
Mettre en cache le résultat au niveau objet
Même optimisée, la requête reste coûteuse à répéter à chaque ouverture d’article dans l’éditeur, en particulier via ServerSideRender qui la rejoue à chaque frappe. Un cache objet transitoire évite ce recalcul :
function wpmoderne_articles_une( $categorie ) {
$cle = 'wpm_articles_une_' . md5( $categorie );
$resultat = wp_cache_get( $cle, 'wpmoderne' );
if ( false === $resultat ) {
$resultat = wpmoderne_executer_requete_articles( $categorie );
wp_cache_set( $cle, $resultat, 'wpmoderne', 5 * MINUTE_IN_SECONDS );
}
return $resultat;
}
Une durée de cache de cinq minutes reste largement suffisante pour un bloc « à la une » : un nouvel article publié met au pire cinq minutes à apparaître, un compromis jugé acceptable par la rédaction au regard du gain de performance.
Résultats mesurés
| Étape | Temps de rendu du bloc |
|---|---|
| Requête initiale, sans optimisation | 6,2 s |
| Après réduction des champs chargés | 1,1 s |
| Après ajout du cache objet | 380 ms |
Ce que cet article ne couvre pas
Le CDN d’images, qui joue également un rôle important sur un site de cette taille pour le poids des vignettes affichées dans le bloc, relève d’une configuration d’hébergement distincte, sans lien avec la requête elle-même. La monétisation publicitaire, insérée par ailleurs entre certains blocs de la page d’accueil, suit une logique complètement indépendante de cette optimisation.
En résumé
Sur un volume de contenu important, les paramètres par défaut de WP_Query deviennent rapidement le principal facteur de lenteur d’un bloc, bien avant le rendu JavaScript ou CSS. Réduire la requête au strict nécessaire, puis ajouter un cache objet à durée courte, a suffi ici à ramener un temps de rendu problématique à un niveau largement acceptable pour la rédaction.