Chapitre 13 sur 20

Optimiser les performances de WordPress

Laisser un commentaire

WordPress c’est un peu comme Windows. Lorsqu’il vient d’être installé, il réagit au quart de tour. Néanmoins, petit à petit, au fur et à mesure qu’on y installe des choses, il tend à ralentir.

Refuser d’ajouter des plugins à WordPress reviendrait à se priver d’un de ses principaux atouts : son extensibilité. Afin de profiter de la richesse de l’écosystème tout en conservant de bonnes performances, nous allons devoir travailler sur plusieurs aspects : hébergement, front, back, base de données. Accrochez-vous, c’est parti !

Les plugins

Dans toute codebase, on se repose sur des librairies, modules ou bibliothèques. Ce sont des dépendances, il s’agit de code tiers : du code que nous n’avons pas écrit et qui sera exécuté avec le code du projet. Cela nous permet d’accélérer le développement en nous évitant de tout créer depuis zéro.

Il en va de même pour les plugins WordPress. De la même manière que pour vos dépendances, il faut choisir les plugins avec soin afin de s’assurer qu’ils soient de bonne qualité : fiable, sécurisé et rapide. Combien de modules npm sont obèses ? Combien de librairies PHP contiennent des failles de sécurité ? Choisir avec soin est essentiel, les plugins ne font pas exception !

La majeure différence entre les plugins WordPress et les dépendances classiques réside dans le fait que les plugins ont accès à la base de données et peuvent injecter du CSS et du JS dans le front sans votre intervention. Comme l’architecture WP et le schéma de base de données sont standards, c’est vraiment plug n’ play.

L’avantage est évidemment la facilité et la rapidité de mise en place. En revanche, on ne réalise pas forcément ce qui se passe sous le capot. Un plugin, c’est :

  • du code PHP qui s’exécute,
  • potentiellement des requêtes supplémentaires en base de données,
  • potentiellement de nouveaux assets à charger en front (CSS et JS).

Nous devons donc être d’autant plus vigilants qu’un plugin peut impacter ces trois domaines de l’application.

Le front

C’est le plus évident, il s’agit des données que l’on envoie directement au navigateur. Rien que sur ce point, nous avons déjà pas mal à dire. Nous avons deux points sur lesquels travailler :

CSS & JavaScript

Les styles et les scripts sont des éléments qui doivent non seulement être téléchargés, mais aussi parsés : le CSS est compilé et le navigateur créé le CSSOM tandis que le JavaScript est parsé, compilé puis interprété.

Processus de rendu du JavaScript
Le temps avant exécution du JavaScript ne s'arrête pas à son chargement

Les éléments du thème

Il y a tout d’abord le CSS et le JS que nous écrivons nous-même. Sur ce point, l’axe d’amélioration consiste à ne pas importer trop d’éléments.

Par exemple, on ne charge pas jQuery partout si l’on ne s’en sert pas. De la même manière, si on utilise Bootstrap ou d’autres librairies, on essaye de n’importer que les parties dont nous avons besoin plutôt que l’ensemble. Par ailleurs, dans un cas comme dans l’autre, on peut aujourd’hui se passer de ces librairies dont la plus-value est discutable (pub : utilisez ƒlightDom).

Premièrement, concernant le JavaScript, il est préférable d’importer via ESM plutôt que d’injecter des scripts depuis des CDN publics. Cela nous permet de profiter du tree shaking (suppression du code mort). Si vous utilisez Steroids, c’est déjà configuré par défaut, sinon, lisez mon article sur Rollup ou renseignez-vous sur les possibilités offertes par les outils que vous utilisez.

Deuxièmement, toujours dans la logique de n’importer que le strict nécessaire, on peut utiliser le dynamic loading. De cette manière, aussi bien le CSS que le JavaScript, ne sont chargés que lorsque c’est nécessaire. Ainsi, vous ne chargez pas tous les styles de la homepage sur une page de blog.

Ces deux fonctions sont nativement offertes avec Steroids. Si vous l’utilisez déjà, vous n’avez qu’à en tirer parti, dans le cas contraire, vous pouvez vous inspirez du code de Steroids afin d’obtenir ces mêmes comportements avec vos outils actuels.

Le cas jQuery

Pour des raisons historiques, jQuery est livré et chargé par défaut avec WordPress. Si vous réalisez votre thème sur-mesure, vous n’en avez très certainement pas besoin.

Cependant, de nombreux plugins requerront la bibliothèque. Pour cette raison, il faut configurer WordPress pour ne pas charger jQuery par défaut, tout en offrant la possibilité de la charger pour les plugins en ayant besoin.

// Totalement supprimer jQuery
add_filter('wp_default_scripts', function (&$scripts) {
    // jQuery est utilisé dans le backoffice, on ne le supprime qu'en front
    if (!is_admin()) $scripts->remove('jquery');
}

// Offrir un jQuery plus moderne au besoin
add_filter('wp_default_scripts', function (&$scripts) {
    if (!is_admin()) $scripts->remove('jquery');

    // On définit que le jquery.js du thème sera chargé en cas de besoin (rien n'est chargé sinon)
    $scripts->add('jquery', get_template_directory_uri() . '/scripts/jquery.js', [], false);
}

Le fait de pouvoir définir notre propre jQuery permet d’avoir une version plus moderne et plus légère que celle utilisée par défaut. Si vous utilisez Steroids, il suffit de vous diriger vers le fichier de config du thème et d’activer les options correspondantes.

Les éléments des plugins

On a beaucoup moins d’influence sur ce que font les plugins. En effet, par définition, il s’agit de code tiers qu’il est difficile de modifier (voir déconseillé).

Comme nous l’avons mentionné, les plugins peuvent tout à fait ajouter des assets CSS et JavaScript au niveau du front. C’est parfois souhaitable, mais pas toujours. Ce que nous pouvons faire, c’est supprimer ces éléments sur une ou toutes les pages.

Par exemple, un plugin n’est utilisé que sur la page de contact, alors nous supprimerons les fichiers de styles et le JS partout sauf sur cette page.

Pour ce faire, j’utilise Asset CleanUp sur absolument tous mes sites. Le plugin existe en version gratuite et premium. Il permet en effet de voir ce qui est chargé sur chaque page et de choisir de ne pas le charger : sur une page ou toutes les pages et de mettre en place des exceptions.

Vue de l'onglet assets cleanup sur le backoffice
Sur chaque page, Asset Cleanup permet de voir et contrôler l'ensemble des assets

Les images

C’est une évidence, les images constituent en général l’une des ressources les plus lourde d’un site. On ne va pas se priver d’images pour autant, mais connaître les règles de l’art permet déjà de gagner énormément.

De manière générale, en ce qui concerne les images du thème notamment, commencer par bien comprendre les différents formats, la définition et les résolutions permet de gagner énormément en taille et qualité.

L’article précédent explique aussi comment servir des images de manière responsive, c’est à dire que vous ne servez évidemment pas la même image à un internaute connecté depuis un mobile, avec un petit écran, qu’un autre sur un ordinateur de bureau avec un écran 5k.

Les images de votre thème doivent donc être dans le (ou les) bon format, dans la (ou les) bonne définition et évidemment encodées avec soin. J’utilise en général ShortPixel pour encoder les JPEG et PNG et SVGOMG pour optimiser les SVG.

Bien entendu, j’encode également toutes les images du thème en WebP afin de servir ce format aux navigateurs compatibles. Une fois n’est pas coutume, si vous utilisez Steroids, cela est fait pour vous, dans le cas contraire, vous pouvez consulter mon article sur WebP afin de savoir comment mettre cela en place.

Voyons maintenant ce que nous pouvons faire concernant les images de la médiathèque de WordPress.

La définition

Lorsque vous uploadez une image dans la médiathèque, WordPress la convertit en plusieurs tailles. Vous pouvez ajouter de nouvelles tailles via le functions.php en utilisant add_image_size.

Les arguments sont au nombre de quatre :

Le comportement de crop peut être à true (recadrera l’image), false (ajustera en l’étirant) ou recevoir un tableau pour préciser les positions x et y pour le cropping (respectivement x_crop_position et y_crop_position).

Gardez à l’esprit qu’il n’y a pas de cropping ou d’étirement si seule une des deux valeurs, largeur ou hauteur, est spécifiée. Dans ce cas, la valeur non spécifiée sera calculée proportionnellement pour conserver le ratio d’origine.

add_image_size('nouveau_format', 1400);

// On peut aussi redéfinir un format existant
add_image_size('large', 1000, '', true);

Par défaut, les nouveaux formats ne sont pas sélectionnables depuis la médiathèque. Pour cela, il faut manuellement le préciser.

add_filter('image_size_names_choose', function ($sizes) {
    $custom_sizes = [
        // vous définissez tous les formats à ajouter à la média library
        'nouveau_format' => 'Nouveau format'
    ];

    return array_merge($sizes, $custom_sizes);
});

La compression

Vous le savez sans doute, WordPress créé de nouvelles tailles pour chaque image que vous ajoutez à la bibliothèque des médias. On peut lui préciser, via les réglages du functions.php un taux de compression (du 0 à 100, de plus compressé au moins compressé) pour le jpeg.

add_filter('jpeg_quality', function ($arg) { return 80; });

Si vous utilisez Steroids, Il vous suffit de définir la qualité attendue dans le fichier de configuration. La compression native permet d’obtenir des résultats corrects sans ajouter de plugin et en conservant l’ensemble des traitements d’images sur votre serveur.

Dans le cas du natif, j’utilise en complément WebP Converter afin de pouvoir aussi servir les images en WebP aux navigateurs compatibles. Ce plugin effectue aussi l’ensemble des traitements sur votre serveur.

WebP Converter nécessite de déclarer quelques filtres pour fonctionner avec l’architecture de Steroids.

// Filters to set proper assets directory for webp converter
add_filter('webpc_dir_name', function ($value, $directory) {
    return str_replace('wp-content/', '', $value);
}, 10, 2);

add_filter('webpc_site_root', function ($path) {
    return WP_CONTENT_DIR;
});

add_filter('webpc_site_url', function ($path) {
    return WP_CONTENT_URL;
});

Cependant, pour de meilleurs résultats, il est préférable d’utiliser un service spécialisé. Cette approche présente un double avantage :

De toutes les solutions existantes, il n’y a pas à hésiter : ShortPixel offre de très loin les meilleurs performances. En plus d’optimiser vos images JPG, PNG et GIF (ainsi que les PDF), c’est le seul plugin à également convertir vos images aux nouveaux formats WebP et AVIF !

ShortPixel, le service cloud de compression d'images
ShortPixel est le service le plus puissant et complet pour l'optimisation des images

Mais ce n’est pas tout, ShortPixel permet aussi de servir vos images au travers de son réseau CDN en adaptant la taille exacte de chaque image à l’écran de l’internaute, et ça, c’est révolutionnaire !

Le responsive

Compresser les images c’est bien, mais proposer plusieurs options de taille aux navigateurs, c’est encore mieux. Cela est possible grâce à la balise <img> et a srcset. WordPress incorpore cette balise par défaut depuis la version 4.4.

Vous avez à votre disposition toute une panoplie de hooks et fonctions afin d’en tirer le meilleur. Pour vos templates, vous pouvez utiliser wp_calculate_image_srcset conjointement avec wp_calculate_image_sizes afin de générer du markup responsive.

Pour le HTML généré par les utilisateurs, on s’appuiera sur les hooks wp_calculate_image_srcset et wp_calculate_image_sizes. Pour plus de détails sur l’ensemble de ces fonctionalités, vous pouvez lire l’article Responsive Images du blog WordPress.

Sachez que si pour une raison ou une autre, vous souhaitez désactiver totalement les srcset, cela ne requiert qu’une seule ligne.

add_filter('wp_calculate_image_srcset_meta', '__return_null');

Gros régime

Qu’il s’agisse du HTML, du CSS et du JS, avant même d’aborder la compression, on peut supprimer les caractères inutiles :

Vous l’avez peut être déjà en place dans votre process de développement pour les assets du thème, cependant, de nombreux développeurs de plugins ne prennent pas cette peine.

Concaténation et minification des assets Asset Cleanup
Asset Cleanup couvre aussi ce besoin

Avec Asset CleanUp, on peut à la fois minifier et concaténer (réunir plusieurs fichiers en un seul) nos assets CSS et JS.

Le back

Si le front a un impact direct sur le temps de chargement et de parsing, le back lui, influence le temps que le serveur va mettre avant de répondre au navigateur, retardant d’autant le téléchargement de la page !

Les images

Puisque nous parlions des images juste avant, sachez aussi que, même si elles ne sont pas servies au front, toutes les variantes de tailles des images viennent s’accumuler sur votre serveur.

Pour cette raison, autant supprimer les format non utilisés. Ce sont autant de fichiers qui s’amoncellent inutilement sur votre serveur. Vous pouvez dans un premier temps établir la liste de tous les formats générés par WordPress via la wp-cli.

php wp-cli media image-size
+-------------------------------+-------+--------+------+-------+
| name                          | width | height | crop | ratio |
+-------------------------------+-------+--------+------+-------+
| full                          |       |        | N/A  | N/A   |
| large                         | 4000  | 4000   | soft | N/A   |
| 2048x2048                     | 2048  | 2048   | soft | N/A   |
| 1536x1536                     | 1536  | 1536   | soft | N/A   |
| large                         | 1024  | 1024   | soft | N/A   |
| large                         | 1024  | 1024   | soft | N/A   |
| medium_large                  | 768   | 0      | soft | N/A   |
| shop_single                   | 600   | 0      | soft | N/A   |
| woocommerce_single            | 600   | 0      | soft | N/A   |
| shop_catalog                  | 300   | 300    | hard | 1:1   |
| woocommerce_thumbnail         | 300   | 300    | hard | 1:1   |
| medium                        | 300   | 300    | soft | N/A   |
| thumbnail                     | 150   | 150    | hard | 1:1   |
| woocommerce_gallery_thumbnail | 100   | 100    | hard | 1:1   |
| shop_thumbnail                | 100   | 100    | hard | 1:1   |
| shop_thumbnail                | 0     | 0      | soft | N/A   |
| shop_catalog                  | 0     | 0      | soft | N/A   |
| woocommerce_gallery_thumbnail | 0     | 0      | soft | N/A   |
| woocommerce_single            | 0     | 0      | soft | N/A   |
| woocommerce_thumbnail         | 0     | 0      | soft | N/A   |
| 2048x2048                     | 0     | 0      | soft | N/A   |
| 1536x1536                     | 0     | 0      | soft | N/A   |
| shop_single                   | 0     | 0      | soft | N/A   |
+-------------------------------+-------+--------+------+-------+

On constate ici que WooCommerce déclare un certain nombre de tailles différentes. Ainsi, dans le cas où certaines tailles ne sont pas utilisées, on peut les désactiver depuis les fonctions du thème. Dans Steroids, cela se fait depuis inc/image-management.php.

// On veut ici désactiver la génération des medium_large et des @2x
add_filter('intermediate_image_sizes_advanced', function ($sizes){
    unset($sizes['medium_large']);
    unset($sizes['1536x1536']); // 2x medium-large size
    unset($sizes['2048x2048']); // 2x large size
    return $sizes;
});

Vous l’avez peut-être constaté, certaines images sont suffixées avec scaled. Cela signifie que l’image était d’une définition trop importante (suppérieure à 2560px par défaut). Ce type d’image n’est en général pas adapté pour le web car trop grande et lourde. WordPress génère donc automatiquement une image d’un maximum de 2560px (largeur ou hauteur en fonction du plus grand).

Cette fonction permet avant tout d’utiliser une image de dimmension “raisonnable” en front tout en conservant l’image originale sur le serveur. L’image originale peut être utilisée par le thème, via wp_get_original_image_path, dans le cas d’une fonction nécessitant une très haute définition et sera par ailleurs utilisée pour re-générer les miniatures. Cependant, l’image scaled sera utilisée en lieu et place de l’originale dans l’éditeur (c’est l’url de la scaled que vous verrez dans la médiathèque).

Si vous dimensionnez vos images avant upload, vous ne rencontrerez jamais le cas. Cependant, si vous envoyez des images en haute définition, vous pourriez avoir besoin de modifier la taille maximum ou même de la désactiver complètement.

// Désactive la fonctionnalité
add_filter('big_image_size_threshold', '__return_false');

// Change la taille maximale à partir de laquelle on resize
add_filter('big_image_size_threshold', function () { return 3000; });

Sachez par ailleurs que dans Steroids, il existe un paramètre permettant d’activer l’écrasement de l’image d’origine par l’image large. Lorsque cette fonctionnalité est activée via le config.php, la génération scaled est automatiquement désactivée. Cette fonction permet de ne pas surcharger le serveur avec des images inutiles.

Les plugins

Nous avons déjà vu dans la partie concernant le front que l’on peut désactiver le chargement du CSS et du JavaScript des plugins sur certaines pages.

Cependant, comme je l’ai expliqué au début de ce chapitre, un plugin impacte les performances non seulement car il peut ajouter des assets CSS et JS, mais aussi car il peut effectuer des s à la base de données et nécessiter du temps de calcul PHP.

Ces deux formes de traitement ralentissent la génération de la page. C’est pourquoi, dans la même logique que ce que nous avons fait pour le front, je recommande de désactiver les plugins lorsqu’ils n’ont pas d’utilité.

Interface de gestion des plugins de Asset Cleanup
On désactive tous les plugins qui ne servent pas en front

Par exemple, un plugin de formulaire de contact fera à chaque chargement de page plusieurs requêtes à la base de données : quels sont les administrateurs du site, quels sont leurs emails, quelle est la configuration d’envoie des notifications de formulaire.

Voilà autant de requêtes que l’on peut éviter sur toutes les pages où le plugin ne sert à rien, certains plugins ne sont même utiles qu’en back-office. Cette étape est réellement une des plus efficace afin de préserver les performances serveur de WordPress. Nous confions à nouveau cette tâche à Asset CleanUp. Cependant, seule la version pro du plugin est en capacité de totalement désactiver les plugins sur certaines pages.

Savoir pour agir

Comme nous l’avons déjà mentionné, de très nombreux facteurs influencent la vitesse du site. Cependant, lorsque l’on veut améliorer les performances, travailler à l’aveugle est très compliqué.

Interface du plugin Query Monitor
Audit de performance sur Alphapole

C’est pourquoi il existe un plugin permettant d’inspecter ce qui se passe sous le capot de WordPress :

Ce merveilleux plugin s’appelle Query Monitor. Il vous permet de rapidement diagnostiquer afin de prendre des décisions éclairées.

La base de données

Avec le code PHP qui prend du temps à s’exécuter, le base de données est le second pilier de la performance côté serveur. PHP a en effet besoin des données contenues dans cette dernière afin de générer les pages. Et si la base est lente à répondre, PHP ne peut pas commencer son travail !

C’est pourquoi la base de donnée requiert une attention toute particulière. Premièrement, si vous avez été vigilant sur les plugins que vous avez installé et que vous n’avez activé que les plugins utiles sur vos pages, un certain nombre de requêtes ont déjà été évitées.

Malgré tout, comme la base de données de WP est compatible avec le moteur MyISAM, elle n’utilise pas de clefs étrangères. Le principal inconvénient lié à cette absence est qu’il est possible que des données soient orphelines. Des options de plugins désinstallés, des metas de posts qui ont été supprimées…

En outre, les plugins peuvent (et le font) créer de nouvelles tables et/ou utiliser les tables existantes pour lire et écrire des données. Rien ne dit que les requêtes sont optimisées et les bons index créés.

À moins d’avoir une documentation exhaustive pour chaque plugin (impossible), il n’est pas possible de s’assurer que ces requêtes ne ralentissent pas les performances. Cette partie d’optimisation est assez poussée, vous devez inspecter votre base en CLI ou via un outil graphique tel que PHPMyAdmin. Si vous ne maîtrisez pas les index de table, je vous invite à lire mon article sur MySQL.

Régulièrement passer le balais

Comme nous venons de le voir, entre les plugins supprimés, les posts effacés, les données expirées, il y a de fortes chances que votre base de données ait besoin d’un petit nettoyage.

La table qui pose le plus souvent problème est wp_options car il s’agit d’une table générique dans laquelle le core, les plugins et les thèmes peuvent stocker des données. On utilise la fonction add_option pour ce faire.

En outre, toutes les entrées de cette table contiennent une option : autoload, laquelle force la donnée à être chargée en mémoire à chaque chargement de page. De ce fait, si certaines données sont chargées inutilement, les performances du site sont inévitablement impactées.

Il est évidemment possible d’inspecter les données directement depuis la base de données. Mais cette approche est longue et fastidieuse. Je recommande d’utiliser Advanced DB Cleaner pour cette tâche.

Les trois grands types de solutions d'hébergement
J'inspecte ici d'un coup d'œil les données périmées ou orphelines et j'ai la possibilité de les effacer

Le plugin permet de voir toutes les tables de la base de données, de visualiser l’ensemble des données de la table options (avec un filtre sur l’autoload) ainsi que de lister les tâches cron.

Pour chacun de ces éléments, le plugin permet de savoir quel est le “détenteur” de la donnée ou de la tâche et bien entendu de supprimer l’élément s’il est caduque. En plus de pouvoir supprimer les tables, Advanced DB Cleaner permet aussi de les optimiser pour des requêtes plus rapides.

Gestion des versions

La gestion de versions native de WordPress est extrêmement pratique. Elle permet en effet de sauvegarder automatiquement votre travail en cours et de pouvoir revenir à d’ancienne versions d’une page ou d’un article.

Cependant, sans surprise, ces données finissent par prendre de la place dans la base de données. Comme vous l’avez peut-être remarqué dans la capture d’écran de Advanced DB Cleaner, le nombre de révisions présentes dans la base est indiqué et il est facile de les supprimer.

Toutefois, on peut aussi limiter le nombre de révisions que WordPress sauvegardera. Pour cela, il faut declarer la constante WP_POST_REVISIONS dans le wp-config.php. Celle-ci peut prendre trois valeurs :

Dans Steroids, cette valeur se définit en toute simplicité dans le fichier .env et sa valeur par défaut est de 10.

Mettre en place du cache

Vous l’avez compris, côté serveur, quand nous faisons face à des lenteurs, c’est en général soit du traitement PHP complexe, soit des requêtes MySQL qui prennent du temps.

Le cache offre une réponse à ces deux problèmes et se positionne à plusieurs niveaux :

Cache objet

Le premier est un cache mémoire permettant de sauvegarder des données qui seront réutilisées plutôt que de les requêter et/ou calculer de nouveau. C’est un cache extrêmement rapide, mais il n’est pas persistant (il n’est pas utilisé entre différentes pages). Il est abondamment utilisé par WP core et il est tout à fait possible de l’utiliser dans vos templates.

Cette API se compose d’une demi-douzaine de fonctions dont vous trouverez les références sur la documentation. Sachez par ailleurs qu’il est possible de rendre ce cache persistant avec Redis ou Memcached par exemple.

Les transients

Les transients permettent de stocker dans la base de données des valeurs pre-calculées. L’API de transient est très similaire à l’API de la table wp_options, la différence est que les transients possèdent une date de péremption après laquelle ils seront automatiquement effacés. Par ailleurs, contrairement aux options, les transients sont susceptibles d’être stockés de manière plus performante si un mécanisme de cache tel que Memcached ou Redis est en place.

En outre, la principale différence entre les transients et le cache objet est la persistance. Le cache objet n’est pas persistent par défaut tandis que les transients le sont. À cet titre, si une solution de persistence telle que Redis ou Memcached est configuré, l’API de transient utilisera directement l’API de cache objet. Pour référence, vous retrouverez toutes les fonctions de l’API transient sur la documentation.

Cache de page

Contrairement aux deux caches précédents, celui-ci est de plus haut niveau : il ne stocke pas juste quelques données mais l’ensemble du code HTML de la page.

De cette manière, lorsqu’un internaute requiert une page, il n’est même pas utile de lancer un processus PHP ni de consulter la base de données. La page est déjà prête à être transmise à l’internaute.

Évidemment, cette technique présente des limites. Puisque la page est servie telle quelle, il n’est pas possible de la personnaliser spécifiquement pour un seul internaute à un moment donné. On pense par exemple à une page panier qui n’est jamais la même selon les articles qu’elle contient.

Dans ces cas, on désactive le cache pour certaines pages. Ce dernier niveau de cache n’est pas inclus par défaut et requiert un plugin. De très nombreux plugins gratuits et payant répondent à cet usage. De tous ceux que j’ai testé, le plus simple et efficace est WP Super Cache, le plugin créé par Automattic, l’éditeur de WordPress.

Statico-dynamique

Gardez à l’esprit que si un élément dynamique est présent sur toutes les pages, le cache de page ne pourra pas être utilisé. Par exemple, si le header contient le nombre d’articles du panier, alors vous ne pouvez cacher le HTML car il est différent pour chacun.

Une solution acceptable est de servir des cache pour les utilisateurs non concernés par cette fonction : utilisateurs non connectés ou qui n’ont pas un cookie donné par exemple.

L’autre solution est de déporter cette fonctionnalité en AJAX. Vous envoyer alors dans un premier temps une page par défaut (par exemple avec le panier sans le nombre de produits), puis vous faites une requête AJAX pour récupérer les informations en asynchrone et mettre à jour la page.

C’est comme cela qu’est géré le mini panier chez Alphapole.

Cache navigateur

Ce dernier cache s’effectue en réalité côté front car, comme son nom l’indique, ce sont les navigateurs qui mettent en cache. Cependant, c’est bien le serveur qui en dicte les règles.

Ce cache permet au navigateur de servir certains contenus depuis sa mémoire locale plutôt que de télécharger de nouveau certains éléments qu’il possède déjà.

Cette partie mériterait un article à elle seule tant elle est complexe si on entre dans les détails. Par ailleurs, chaque serveur possède ses propres mécanismes de gestion du cache. Avec Apache – qui est le serveur le plus populaire avec PHP – on peut gérer les règles directement depuis le fichier .htaccess.

# On ajoute le type MIME pour les fichiers polices woff et woff2
# Apache ne les connaît pas forcément
AddType font/woff woff
AddType font/woff2 woff2

# On active le header expire
# Puis on définit une politique de cache par type de fichier
ExpiresActive On
ExpiresByType text/html "access plus 1 hour"
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType text/x-javascript "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresDefault "access plus 1 month"

# On supprime le etag pour gagner encore en performance
# En contrepartie, le serveur et le navigateur ne vérifieront plus l'emprunte des fichiers
Header unset ETag
FileETag None

La désactivation des ETag fait que les règles de cache sont strictement respectées sans aucune vérification supplémentaire. Lors de changement de ressources, on préférera changer l’url, c’est le cas par défaut avec Steroids, lequel versionne les assets selon le numéro de version du projet.

Pour NGINX, voici comment on procède :

location ~*  \.(jpg|jpeg|gif|png|svg|js|woff|woff2)$ {
    expires 365d;
}

Comme nous l’avons mentionné, certaines pages ne sont pas à mettre en cache. Normalement, WordPress et les plugins concernés définissent les bons headers, mais mieux vaut quand même vérifier pour en avoir le cœur net. On peut visualiser les headers dans l’onglet “réseau” de la console développeur.

Vérification des règles de cache HTTP
On constate ici que le fichier est mis en cache pour 31536000 secondes, soit 365 jours

Si vous utilisez Steroids, un fichier .htaccess est déjà présent afin de fournir par défaut des réglages performants.

Par ailleurs, certains hébergeurs spécialisés, à l’instar de Kinsta, mettent en place l’ensemble des niveaux de cache pour vous. Vous n’avez alors rien à faire.

Attention aux custom fields

Nous n’allons pas dire le contraire, les champs personnalisés présentent un atout majeur pour la réalisation de sites complexes. Si vous n’utilisez que les fonctions natives, aucun problème.

En revanche, si vous utilisez un plugin tel que ACF, CFS ou Pods pour vous aider dans cette tâche, ils fournissent des fonctions helpers afin de récupérer vos données. Bien que pratiques, ces fonctions sont souvent peu optimisées comparées aux fonctions natives de WP.

Les fonctions natives permettent de drastiquement réduire le temps de génération de page (d’un facteur pouvant aller jusqu’à 2 !). Elles tirent profit du cache natif, cela réduit le nombre de requêtes BDD et l’usage mémoire. Pour vous en convaincre, faites le test vous-même sur une page cible et mesurez avec Query Monitor.

Par exemple, chez ACF, get_field n’est qu’un wrapper autour de get_[post|term|option]_meta. Par ailleurs, si vous n’utilisez plus les fonctions helpers, vous pouvez même totalement désactiver le plugin en front !

Désactiver WP Cron

Sur les serveurs, cron est un programme qui tourne en tâche de fond et qui permet d’exécuter des scripts de manière automatique à intervalles réguliers ou à heures données.

Ce système nécessite un accès direct au serveur, ce qui n’est pas toujours le cas avec les hébergement web. Pour parer à ce manque, WordPress a mis en place un système semblable : le WP cron. Cela permet à WordPress de gérer ses tâches en toute autonomie, sans avoir à configurer le cron du serveur.

Ce système présente cependant deux inconvénients. Comme WordPress ne tourne pas en tâche de fond constamment, il est dépendant du trafic : le cron s’exécute lorsqu’un visiteur consulte le site. De ce fait, certaines tâches peuvent s’exécuter beaucoup plus tard que prévu si le site reste sans visiteurs pendant longtemps (la nuit par exemple).

En outre, comme les tâches ne sont pas indépendantes du processus web, la rapidité du site pour les visiteurs peut s’en trouver impactée. Pour ces deux raisons, il est possible de désactiver le cron de WordPress et de l’appeler directement via le cron système. On le désactive dans le wp-config.php.

define('DISABLE_WP_CRON', true);

Si vous utilisez Steroids, comme d’habitude, vous trouverez le paramètre correspondant dans votre fichier .env.

Par la suite, voici ce que cela donne avec le cron natif.

# Appelle wp-cron toutes les minutes (cron système natif)
* * * * * wget -q -O https://www.my-wordpress.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1

Retenez que selon votre hébergeur, vous disposerez certainement d’une interface graphique pour configurer votre cron. Il faut donc appeler l’url https://www.my-wordpress.com/wp-cron.php?doing_wp_cron en remplaçant évidemment www.my-wordpress.com par l’adresse de votre site.

Une fois que vous avez tout optimisé, il reste un dernier facteur qui a un énorme impact sur les performances : l’hébergement ! C’est ce dont nous parlons dans le prochain chapitre.

Commentaires

Rejoignez la discussion !

Vous pouvez utiliser Markdown pour les liens [ancre de lien](url), la mise en *italique* et en **gras**. Enfin pour le code, vous pouvez utiliser la syntaxe `inline` et la syntaxe bloc

```
ceci est un bloc
de code
```