Drupal 8 est arrivé avec plusieurs améliorations en performance, et qui dit performance dit cache.
Dans cet article on va voir en détail les types de cache fournit par Drupal, et comment les utiliser dans nos modules personnalisés pour garantir une performance optimale aux utilisateurs.
Avant de pencher dans les variétés du cache backend, je tiens à préciser que Drupal 8 fournit des modules installés par défaut :
L'API cache de Drupal utilise plusieurs bins qui sont liés à des tables de cache dans la base de donnée (commencent par le préfixe cache_
), il faut alors commencer par demander un cache bin donné pour pouvoir interagir avec le cache API.
$render_cache = \Drupal::cache('render');
La variable $render_cache
dans le code snippet en-dessus présente un objet du cache bin render, néanmoins le cache dans cet exemple est appelé de manière statique, cependant si on travaille avec des classes qui est bien le cas dans les modules customs Drupal, il est recommandé d'utiliser l'injection des dépendances en injectant le service du cache (cache.render
dans notre exemple).
L'API cache (backend) est basée sur trois principes fondamentaux qu'il faut bien comprendre pour pouvoir les utiliser de manière efficace dans le développement des modules personnalisés :
Le principe des caches tags est simple, ces derniers donnent la possibilité de tager des contenus, éléments du render avec des tags différents et précis, ces tags vont être invalidés par la suite après une action bien définie.
Exemple : Imaginant un simple contenu de type Article qui va être affiché dans sa propre page de détail, page de listing ou autres pages. Si on ne gère pas le cache dans le render array qui permet l'affichage des contenus, ces derniers vont être cachés dans le render array et on va finir par afficher du faux contenus aux utilisateurs.
On peut utiliser le tag node_list
dans tous les render arrays qui affichent les contenus pour s'assurer qu'à chaque modification d'un contenu, tous les renders arrays tagés par le même tag (node_list) vont être invalidés afin de reconstruire le nouveau cache dans les render arrays et afficher le nouveau contenu.
<entity type ID>:<entity ID>
ou config:<configuration name>
, et si l'objet accepte qu'une seule instance on peut utiliser objet
comme cache tag.node_list
, config:system.performance
)Il faut noter que les caches tags sur Drupal 8 ne supportent pas les tags des entités par bundle, ce problème sera résolu dans les prochaines versions de Drupal. En revanche, le module Handy Cache Tags gère cette contrainte de manière efficace et qui permet d'utiliser des tags par bundle (ex: handy_cache_tags:node:article
).
Comme son nom l'indique, un cache context se base sur les contextes définis par Drupal, en d'autres termes les caches contexts permettent de varier le cache dans un render array par chemin, utilisateur, langue, theme ou autres contextes.
Le Cache Max-Age permet de cacher un render array sur une durée bien définie. Il prend le format d'un nombre positif en secondes (0, 60, 100). Exemple d'utilisation du cache dans les render arrays :
//Case of render array
$build['#cache']['max-age'] = 0;
//Case of plugin bloc (OOP way)
public function getCacheMaxAge()
{
return 0;
}
Comme on l'avait vu au début de cet article, Drupal dispose des modules Internal Dynamic Page Cache (gère le cache pour les utilisateurs authentifiés) et Internal Page Cache (gère le cache pour les utilisateurs anonymes), et bien ce dernier ne reconnait pas l'existence du cache max age, en d'autres termes si on rajoute un cache max-age dans un render array, ce dernier va être caché pour les utilisateurs anonymes à cause d'Internal Page Cache qui ne tient pas compte du max-age. Il est déconseillé d'utiliser le cache max-age dans vos développements personnalisés. D'ailleurs le cache max-age n'est pas utilisé dans le code source (Core) de Drupal.