Le guide avancé pour optimiser les performances de WordPress
Publié: 2022-03-11Aujourd'hui, WordPress alimente plus de 30 % d'Internet. Il est facile à utiliser, incroyablement populaire et ne va nulle part de sitôt.
Mais WordPress peut être lent. Alors comment l'optimiser ?
Il existe de nombreux articles sur la façon de régler et d'optimiser WordPress. En fait, WordPress lui-même fournit un guide solide sur l'optimisation de WordPress.
Pour la plupart, ces articles et didacticiels couvrent des concepts assez basiques mais utiles, comme l'utilisation de plugins de cache, l'intégration avec les réseaux de diffusion de contenu (CDN) et la minimisation des demandes. Bien que ces conseils soient très efficaces et même nécessaires, ils ne résolvent finalement pas le problème sous-jacent : la plupart des sites WordPress lents sont le résultat d'un code incorrect ou inefficace.
Par conséquent, cet article vise principalement à fournir aux développeurs et aux sociétés de développement WordPress quelques directives qui peuvent les aider à résoudre les causes sous-jacentes de nombreux problèmes de performances WordPress.
WordPress fournit de nombreuses fonctionnalités axées sur les performances qui sont souvent négligées par les développeurs. Le code qui ne tire pas parti de ces fonctionnalités peut ralentir les tâches les plus simples, telles que la récupération des publications. Cet article détaille quatre solutions possibles, qui résolvent certains des problèmes sous-jacents à la lenteur des performances de WordPress.
Récupération des publications
WordPress offre la possibilité de récupérer n'importe quel type de publication dans la base de données. Il existe trois manières fondamentales de procéder :
Utilisation de la fonction
query_posts()
: C'est une approche très directe, mais le problème est qu'elle remplace la requête principale, ce qui peut entraîner des inconvénients. Par exemple, cela pourrait être un problème si nous voulions déterminer, à un moment donné après avoir récupéré les publications (comme dansfooter.php
), à quel type de page nous avons affaire. En fait, la documentation officielle contient une note déconseillant l'utilisation de cette fonction car vous devrez appeler une fonction supplémentaire pour restaurer la requête d'origine. De plus, le remplacement de la requête principale aura un impact négatif sur les temps de chargement des pages.Utilisation de la fonction
get_posts()
: Cela fonctionne presque commequery_posts()
, mais cela ne modifie pas la requête principale. D'autre part,get_posts()
exécute par défaut la requête avec le paramètresuppress_filters
défini surtrue
. Cela pourrait entraîner des incohérences, en particulier si nous utilisons des filtres liés aux requêtes dans notre code, car les publications que vous n'attendez pas dans une page peuvent être renvoyées par cette fonction.Utilisation de la classe
WP_Query
: À mon avis, c'est le meilleur moyen de récupérer les articles de la base de données. Il ne modifie pas la requête principale et est exécuté de manière standard, comme toute autre requête WordPress.
Mais quelle que soit la méthode que nous utilisons pour interagir avec la base de données, il y a d'autres choses que nous devons considérer.
Limiter la requête
Nous devons toujours spécifier le nombre de messages que notre requête doit récupérer.
Pour ce faire, nous utilisons le paramètre posts_per_page
.
WordPress nous permet d'indiquer -1 comme valeur possible pour ce paramètre, auquel cas le système essaiera de récupérer tous les articles qui remplissent les conditions définies.
Ce n'est pas une bonne pratique, même si nous sommes certains que nous n'obtiendrons que quelques résultats en réponse.
D'une part, nous pouvons rarement être certains de ne récupérer que quelques résultats. Et même si nous le pouvons, ne fixer aucune limite obligera le moteur de base de données à analyser l'intégralité de la base de données à la recherche de correspondances.
À l'inverse, la limitation des résultats permet souvent au moteur de base de données de n'analyser que partiellement les données, ce qui se traduit par un temps de traitement réduit et une réponse plus rapide.
Une autre chose que WordPress fait par défaut, ce qui peut avoir un impact négatif sur les performances, est qu'il essaie d'apporter des messages persistants et de calculer le nombre de lignes trouvées sur la requête.
Souvent, cependant, nous n'avons pas vraiment besoin de ces informations. L'ajout de ces deux paramètres désactivera ces fonctionnalités et accélérera notre requête :
$query = new WP_Query( array( 'ignore_sticky_posts' => true, 'no_found_rows' => true ) );
Exclusion de publications de la requête
Parfois, nous souhaitons exclure certaines publications de la requête. WordPress offre un moyen assez direct d'y parvenir : en utilisant le paramètre post__not_in
. Par exemple:
$posts_to_exclude = array( 1, 2, 3 ); $posts_per_page = 10; $query = new WP_Query( array( 'posts_per_page' => $posts_per_page, 'post__not_in' => $posts_to_exclude ) ); for ( $i = 0; $i < count( $query->posts ); $i++ ) { //do stuff with $query->posts[ $i ] }
Mais bien que ce soit assez simple, ce n'est pas optimal car en interne, il génère une sous-requête. Surtout dans les grandes installations, cela peut entraîner des réponses lentes. Il est plus rapide de laisser ce traitement être effectué par l'interpréteur PHP avec quelques modifications simples :
$posts_to_exclude = array( 1, 2, 3 ); $posts_per_page = 10; $query = new WP_Query( array( 'posts_per_page' => $posts_per_page + count( $posts_to_exclude ) ) ); for ( $i = 0; $i < count( $query->posts ) && $i < $posts_per_page; $i++ ) { if ( ! in_array( $query->posts[ $i ]->ID, $posts_to_exclude ) ) { //do stuff with $query->posts[ $i ] } }
Qu'est-ce que j'ai fait là-bas ?
Fondamentalement, j'ai enlevé une partie du travail du moteur de base de données et l'ai laissé au moteur PHP, qui fait la même chose mais en mémoire, ce qui est beaucoup plus rapide.
Comment?
Tout d'abord, j'ai supprimé le paramètre post__not_in
de la requête.
Étant donné que la requête peut nous apporter des publications que nous ne voulons pas, j'ai augmenté le paramètre posts_per_page
. De cette façon, je m'assure que, même si j'avais eu des messages indésirables dans ma réponse, j'aurais au moins $posts_per_page
messages souhaités là-bas.
Ensuite, lorsque je boucle sur les messages, je ne traite que ceux qui ne sont pas dans le tableau $posts_to_exclude
.
Éviter le paramétrage complexe
Toutes ces méthodes de requête offrent une grande variété de possibilités de récupération des articles : par catégories, par méta clés ou valeurs, par date, par auteur, etc.
Et bien que cette flexibilité soit une fonctionnalité puissante, elle doit être utilisée avec prudence car cette paramétrisation pourrait se traduire par des jointures de tables complexes et des opérations de base de données coûteuses.
Dans la section suivante, nous décrirons une manière élégante d'obtenir des fonctionnalités similaires sans compromettre les performances.
Tirer le meilleur parti des options de WordPress
L'API WordPress Options fournit une série d'outils pour charger ou enregistrer facilement des données. C'est utile pour gérer de petites informations, pour lesquelles d'autres mécanismes proposés par WordPress (comme les publications ou les taxonomies) sont trop complexes.

Par exemple, si nous voulons stocker une clé d'authentification ou la couleur de fond de l'en-tête de notre site, les options sont ce que nous recherchons.
WordPress nous donne non seulement les fonctions pour les gérer, mais il nous permet également de le faire de la manière la plus efficace.
Certaines des options sont même chargées directement au démarrage du système, nous offrant ainsi un accès plus rapide (lors de la création d'une nouvelle option, nous devons déterminer si nous voulons la charger automatiquement ou non).
Considérons, par exemple, un site sur lequel nous avons un carrousel affichant les dernières nouvelles spécifiées dans le back-end. Notre premier réflexe serait d'utiliser une clé méta pour cela comme suit :
// functions.php add_action( 'save_post', function ( $post_id ) { // For simplicity, we do not include all the required validation before saving // the meta key: checking nonces, checking post type and status, checking // it is not a revision or an autosaving, etc. update_post_meta( $post_id, 'is_breaking_news', ! empty ( $_POST['is_breaking_news'] ) ); } ); // front-page.php $query = new WP_Query( array( 'posts_per_page' => 1, 'meta_key' => 'is_breaking_news' ) ); $breaking_news = $query->posts[0] ?: NULL;
Comme vous pouvez le voir, cette approche est très simple, mais elle n'est pas optimale. Il effectuera une requête de base de données en essayant de trouver un message avec une clé méta spécifique. Nous pourrions utiliser une option pour obtenir un résultat similaire :
// functions.php add_action( 'save_post', function ( $post_id ) { // Same comment for post validation if ( ! empty ( $_POST['is_breaking_news'] ) ) update_option( 'breaking_news_id', $post_id ); } ); // front-page.php if ( $breaking_news_id = get_option( 'breaking_news_id' ) ) $breaking_news = get_post( $breaking_news_id ); else $breaking_news = NULL;
La fonctionnalité varie légèrement d'un exemple à l'autre.
Dans le premier morceau de code, nous aurons toujours les dernières nouvelles de dernière heure, en termes de date de publication du message.
Dans le second, chaque fois qu'un nouveau message est défini comme une actualité de dernière minute, il écrasera l'actualité de dernière minute précédente.
Mais parce que nous voulons probablement un article d'actualité à la fois, cela ne devrait pas poser de problème.
Et, à la fin, nous avons changé une requête de base de données lourde (utilisant WP_Query
avec des clés méta) en une requête simple et directe (appelant get_post()
) qui est une approche meilleure et plus performante.
Nous pourrions également faire un petit changement et utiliser des transitoires au lieu d'options.
Les transitoires fonctionnent de la même manière mais nous permettent de spécifier un délai d'expiration.
Par exemple, pour les dernières nouvelles, cela va comme un gant parce que nous ne voulons pas qu'un ancien message soit considéré comme une nouvelle de dernière minute, et si nous laissons la tâche de modifier ou d'éliminer cette nouvelle de dernière heure à l'administrateur, il pourrait oublier de faire ce. Ainsi, avec deux modifications simples, nous ajoutons une date d'expiration :
// functions.php add_action( 'save_post', function ( $post_id ) { // Same comment for post validation // Let's say we want that breaking news for one hour // (3600 = # of seconds in an hour). if ( ! empty ( $_POST['is_breaking_news'] ) ) set_transient( 'breaking_news_id', $post_id, 3600 ); } ); // front-page.php if ( $breaking_news_id = get_transient( 'breaking_news_id' ) ) $breaking_news = get_post( $breaking_news_id ); else $breaking_news = NULL;
Activer la mise en cache persistante
WordPress dispose nativement d'un mécanisme de mise en cache d'objets.
Les options, par exemple, sont mises en cache à l'aide de ce mécanisme.
Mais, par défaut, cette mise en cache n'est pas persistante, ce qui signifie qu'elle ne vit que pendant la durée d'une seule requête. Toutes les données sont mises en cache en mémoire, pour un accès plus rapide, mais elles ne sont disponibles que pendant cette requête.
La prise en charge de la mise en cache persistante nécessite l'installation d'un plug-in de cache persistant.
Certains plugins de cache pleine page sont livrés avec un plugin de cache persistant inclus (par exemple W3 Total Cache), mais d'autres ne le font pas, et nous devons l'installer séparément.
Cela dépendra de l'architecture de notre plate-forme, si nous utiliserons des fichiers, Memcached ou un autre mécanisme pour stocker les données mises en cache, mais nous devrions tirer parti de cette fonctionnalité étonnante.
On pourrait se demander : « Si c'est une si grande fonctionnalité, pourquoi WordPress ne l'active-t-il pas par défaut » ?
La raison principale est que, selon l'architecture de notre plateforme, certaines techniques de cache fonctionneront et d'autres non.
Si nous hébergeons notre site sur notre serveur distribué, par exemple, nous devrions utiliser un système de cache externe (comme un serveur Memcached), mais si notre site Web réside sur un seul serveur, nous pourrions économiser de l'argent en utilisant simplement le système de fichiers mettre en cache.
Une chose que nous devons prendre en compte est l'expiration du cache. C'est l'écueil le plus courant du travail avec la mise en cache persistante.
Si nous ne traitons pas correctement ce problème, nos utilisateurs se plaindront qu'ils ne verront pas les modifications qu'ils ont apportées ou que leurs modifications ont mis trop de temps à s'appliquer.
Parfois, nous allons nous retrouver à faire des compromis entre performances et dynamisme, mais même avec ces obstacles, la mise en cache persistante est quelque chose dont pratiquement toutes les installations WordPress devraient tirer parti.
AJAXer de la manière la plus rapide
Si nous avons besoin de communiquer via AJAX avec notre site web, WordPress propose une certaine abstraction au moment du traitement de la requête côté serveur.
Même si ces techniques peuvent être utilisées lors de la programmation d'outils back-end ou de soumissions de formulaires depuis le front-end, elles doivent être évitées si elles ne sont pas strictement nécessaires.
La raison en est que pour utiliser ces mécanismes, nous sommes obligés de faire une demande de publication dans un fichier situé dans le dossier wp-admin
. La majorité (sinon la totalité) des plugins de mise en cache pleine page de WordPress ne cachent ni les demandes de publication ni les appels aux fichiers administrateur.
Par exemple, si nous chargeons dynamiquement plus de publications lorsque l'utilisateur fait défiler notre page d'accueil, il serait préférable d'appeler directement une autre page frontale, qui bénéficiera de la mise en cache.
Nous pourrions ensuite analyser les résultats via JavaScript dans le navigateur.
Oui, nous envoyons plus de données que nécessaire, mais nous gagnons en termes de vitesse de traitement et de temps de réponse.
Détruisez la notion que WordPress est juste lent
Ce ne sont là que quelques conseils que les développeurs devraient prendre en compte lors du codage pour WordPress.
Parfois, nous oublions que notre plugin ou notre thème peut avoir besoin de vivre avec d'autres plugins, ou que notre site peut être servi par une société d'hébergement qui dessert des centaines ou des milliers d'autres sites avec une base de données commune.
Nous nous concentrons uniquement sur la façon dont le plugin devrait fonctionner et non sur la façon dont il gère cette fonctionnalité, ou comment le faire de manière efficace.
D'après ce qui précède, il est clair que les causes profondes des mauvaises performances de WordPress sont un code mauvais et inefficace. Cependant, WordPress fournit toutes les fonctionnalités nécessaires via ses différentes API qui peuvent nous aider à créer des plugins et des thèmes beaucoup plus performants sans compromettre la vitesse de la plate-forme globale.