Web

Comment Drupal gère au mieux la performance de vos pages (gestion du cache) ?

by Benjamin Hoquy 31 mai 2021

Afin de rester compétitif et performant face aux autres CMS, Drupal a dû mettre en place une politique de cache performante. La gestion du cache a pour but d’améliorer le temps de réponse du site internet et d’éviter la surcharge du serveur. Ce temps de réponse est devenu un levier direct d’augmentation du trafic, notamment par le ranking réalisé par Google. Une gestion de cache performante permet également de réduire les requêtes et les calculs pour les serveurs. Il s’agit donc d’une démarche d’éco-conception des solutions web modernes.

Comment la politique de gestion de cache Drupal s’établit-elle ?

La politique de gestion de cache Drupal s’établit grâce à la cache API. Il s’agit de l’ensemble du code fourni par Drupal servant à la gestion du cache. Cet ensemble s’articule autour de trois axes majeurs : les cache tags (qui ciblent les éléments dont le cache d’une page dépend), les cache contexts (qui font varier le cache en fonction d’un élément lié à la navigation) et le cache max-age (qui donne la durée de vie maximale du cache de la page). Quand une page est construite en Drupal, une combinaison de cache tags, de contexts et d’un max est associée. Dès lorsque l’un de ces critères devient obsolète, ou qu’un tag est invalidé, le cache de la page demandée est régénéré puis servi à l’utilisateur. Le jeu consiste, via la combinaison de ces trois systèmes, à obtenir le cache le plus performant possible.

Pour que la politique du cache d’une page soit performante, il faut que le cache réponde aux deux règles suivantes : il doit rester flexible et le système doit pouvoir invalider le cache seulement si un ou plusieurs éléments ont été modifiés. La même version de la page en cache doit servir le plus d’utilisateurs possible. Ces deux règles ne sont pas absolues, mais donnent une bonne base pour un site building classique (construction d’un site en utilisant seulement le back office et des modules ne fournissant pas la communauté). Il est très rarement nécessaire d’interagir avec la cache API. En effet, Drupal a une bonne gestion native de son cache. Mais lors de développements spécifiques, ou d’un développement de module pour la communauté, il est parfois nécessaire d’interagir avec la cache API pour répondre à un besoin et à des contraintes particulières, qui ne peuvent être gérées nativement.

Les cache tags

Les cache tags permettent de cibler un élément précis dont le cache de la page dépend. Mais le cache de l’élément ne dépend pas de sa durée de vie, d’un contexte utilisateur ou du système. Sur une même page, une multitude de cache tags coexistent, chacun ciblant un élément de la page. Drupal fournit par défaut une liste de cache tags [{entity_type} : {id}, {entity_type}_list, config:{ma_config},library_info].

Mais il est possible de créer ses propres cache tags afin de cibler des éléments et d’ajouter des règles d’invalidation custom. Il est également possible de surcharger la liste de cache tags d’une page afin d’affiner la gestion du cache de la page. Plus concrètement, les cache tags permettent d’invalider le cache d’une page. Par exemple, dans le cas d’un nœud [contenu], le cache tag de la page sera « node:{identifiant_du_noeud}”. Lors de la modification du nœud, Drupal invalidera le cache tag “node:{identifiant_du_noeud}”, ce qui aura pour effet d’invalider toutes les pages du site qui contiennent ce cache tag.

cache Drupal

Il est possible d’ajouter des cache tags dès que le système par défaut n’est plus suffisant. Par exemple, pour un listing d’articles où l’on souhaite invalider le cache pour chaque modification d’un même type de contenu (articles), l’injection du cache tag custom peut s’effectuer dans un hook ou dans un contrôleur, selon le mode de rendu de la page qui a besoin de ce cache tag. Ici, le cache tag qui sera ajouté pour le listing sera :

 $variables[« #cache"]["tags"][] = 'all_articles_listing';

Pour invalider ce cache tag, il faut d’abord définir à quel moment le cache doit être invalidé. Dans le cas du listing, c’est à chaque mise à jour d’un article, afin que le contenu mis à jour ou que le nouveau contenu s’affiche. Le code correspondant sera le suivant :

function module_node_presave [EntityInterface $entity) {
if ($entity-> getType() === 'articles') {
Cache : : invalidateTags('all_articles_listing');
}
}

Grâce à ce code, dès qu’un article sera enregistré (création ou mise à jour), toutes les pages qui contiennent le cache tag« all_articles_listing” verront leur cache vidé. Certains modules contrib (fournis par la communauté) ajoutent des cache tags. Handy cache tags est couramment utilisé afin d’ajouter des cache tags qui s’avèrent souvent manquants dans des développements custom. Ce module permet d’ajouter de la finesse dans la gestion des cache tags des entités. Grâce à lui, il est en effet possible d’ajouter des tags pour n’importe quel type d’entité, et même de spécifier le bundle de l’entité [ex. handy_cache_tags: [entity_type]:[entity_bundle]], ce qui n’est pas possible avec les tags fournis par le core Drupal.

Les cache contexts

Le cache contexts permet de placer en cache plusieurs versions d’une page en fonction d’un contexte lié à la navigation. Mais, il ne dépend pas de la durée de vie de la page ni d’un élément précis de cette page. Drupal fournit par défaut une liste de cache contexts assez complète. Comme pour les cache tags, il reste toujours possible d’en ajouter si nécessaire.

 cookies
:name
headers
:name
ip
languages
:type
protocol_version// Available in 8.9.x or higher.
request_format
route
.book_navigation
.menu_active_trails
:menu_name
.name
session
.exists
theme
timezone
url
.path
.is_front// Available in 8.3.x or higher.
. parent
.query_args
:key
.pagers
:pager_id
.site
user
.is_super_user
.node_grants
:operation
.permissions
.roles
:role

Les cas d’usage des cache contexts sont nombreux. Le cas d’usage le plus fréquent est dans la gestion du fil d’Ariane pour qu’il soit différent sur toutes les pages. Dans ce cas, le cache context « ‘url.path’” est utilisé. Le cache context est aussi utilisé pour le multilingue : une même page sera mise en cache pour chacune de ses langues, et le système renverra la langue correspondante à l’utilisateur en fonction de son contexte.

Le cache max-age

Le cache max-age permet de définir la durée de validité maximale du cache de la page. Par défaut, il est préconisé d’y mettre une valeur élevée, de l’ordre d’un an pour éviter des régénérations de cache inutiles. Sa valeur peut être surchargée sur chaque page afin de désactiver le cache en y affectant la valeur 0. Il est aussi possible de programmer l’expiration du cache d’une page à une date précise, ou à intervalle régulier.

BigPipe

BigPipe n’est pas à proprement parler impliqué dans la gestion du cache, mais contribue à améliorer les performances du site. BigPipe est originellement un module intégré au corps de Drupal 8.1. Il permet de donner une impression de rapidité au site. Grâce à BigPipe, la page n’est pas livrée à l’utilisateur en une fois, mais en plusieurs : à l’arrivée sur le site web, au lieu d’une page blanche pendant X secondes, c’est une version allégée de celle-ci qui s’affiche, avec quelques blocs manquants, lesquels s’afficheront de manière différée. La page complète ne sera pas affichée plus rapidement, mais l’utilisateur pourra accéder plus tôt à une partie ciblée de la page.

Pour aller plus loin

Pour aller plus loin dans la gestion du cache, des outils complémentaires existent, comme Varnish ou Redis, qui peuvent s’avérer très performants. Varnish est un reverse proxy qui répond à la place du serveur web. Il renvoie au client des pages qu’il aura mises en cache préalablement, ce qui évite de devoir passer par Drupal qui est plus lent à répondre. Pour pouvoir utiliser Varnish sur Drupal, les modules “Purger”et “Varnish purger” sont nécessaires afin que le site puisse invalider du cache Varnish. La purge de cache Varnish s’effectue par défaut via le cron Drupal, mais il est plutôt préconisé d’utiliser les crons systèmes. La cache API Drupal est toujours compatible avec Varnish, donc les politiques de caches mises en place grâce aux cache tags, contexts ou max-age seront toujours valides. Mais au contraire, BigPipe n’est pas compatible. Malheureusement les ESI, permettant de découper la page en blocs avec une gestion de caches différente, ne sont toujours pas implémentés. Dans ce cas, le cache est alors géré de manière globale sur la page et non atomique.

cache drupal

La gestion de cache en base de données de Drupal peut être un frein aux performances. Pour pallier ceci, il est possible d’utiliser Redis (via le module « Redis »), grâce auquel le cache est déplacé dans la RAM, au lieu d’être stocké en base de données. Ce mouvement améliore grandement les vitesses de chargement, la lecture de tableau stocké en RAM étant plus rapide qu’une requête à la base de données. Memcached (via le module « Memcache”) peut aussi être une solution aux problèmes de performances des caches de bases de données. Memcached et Redis ont des fonctionnements assez similaires.

Benjamin Hoquy

Benjamin Hoquy

Développeur Backend

Benjamin, Développeur Backend chez Kaliop depuis 3 ans. Expert technique, il travaille principalement sur des projets de sites Drupal et partage constamment ses bonnes pratiques.

Commentaires

Ajouter un commentaire

Votre commentaire sera modéré par nos administrateurs

Vous avez un projet ? Nos équipes répondent à vos questions

Contactez-nous