Drupal > Un nouveau module pour supprimer les divs entourant vos champs à la demande
Résumé
Les derivative plugins sont une fonctionnalité puissante de Drupal, permettant de générer dynamiquement des plugins à partir d’une classe de base (ex. : un bloc par entité Block Content).
Mais attention : leur mauvaise utilisation peut transformer votre site en un monstre lent et instable. En générant des milliers de définitions de plugins (via des champs inline entity reference, des dérivations en cascade...etc.), vous risquez de saturer le cache (cache_discovery), de déclencher des reconstructions coûteuses à chaque modification, et de rendre votre site inutilisable.
Solution : limitez les derivatives aux cas strictement nécessaires, évitez les chaînes de dérivation, et privilégiez les configurations plutôt que les définitions dynamiques.
Pourquoi les plugins rendent Drupal si puissant ?
Drupal doit une grande partie de sa flexibilité à son système de plugins, qui permet aux modules d’étendre les fonctionnalités natives sans modifier le cœur. Quelques exemples concrets :
- Créer un bloc personnalisé,
- Ajouter un type de champ, un formatter ou un widget,
- Étendre CKEditor (filtres, barres d’outils),
- Intégrer des composants SDC (via YAML converti en plugin),
- Définir un type d’argument de vue ou un filtre.
L’API des plugins offre :
- Une découverte automatique des plugins actifs dans les modules,
- Un système de cache pour optimiser les performances.
Différence clé avec les Event Listeners :
- Un plugin est configurable (il peut inclure son propre formulaire de configuration), contrairement à un event listener.
- Un module peut fournir un plugin pour un autre module sans dépendance forcée. Si le module "parent" (ex. : CKEditor) n’est pas activé, le plugin est simplement ignoré. Avec les event listeners, l’injection de dépendances impose que le module parent soit actif.
Les Derivative Plugins : une arme à double tranchant
Le principe
Les derivatives permettent à un module de générer dynamiquement des plugins à partir d’une classe de base.
Exemple emblématique : Le module block_content crée un plugin de bloc pour chaque entité Block Content. Ces entités, similaires aux nœuds, sont conçues pour être réutilisées dans les régions de la page (via l’interface d’affichage des blocs).
→ Avantage : Vous pouvez ajouter un bloc "FAQ" à toutes vos pages produits sans écrire une ligne de code.
Le problème : une bombe à retardement pour votre site
Le système de plugins de Drupal n’est pas optimisé pour gérer un grand nombre de définitions. Voici pourquoi les derivatives deviennent dangereux :
1. L’explosion du cache (cache_discovery)
- Chaque type de plugin a une seule entrée en cache, contenant toutes ses définitions.
- Exemple : Si vous avez 10 000 Block Content, leur cache pèse plusieurs dizaines de Mo (j’ai vu des entrées à 40 Mo+ !).
- Pire : À chaque ajout/modification d’un Block Content (ex. : un bloc "Hero" ou "FAQ" dans une recette), toute l’entrée de cache est invalidée. Drupal doit alors recharger toutes les définitions pour la reconstruire.
2. Pas de filtrage en base de données
- Quand Drupal charge un plugin, il doit charger toutes les définitions depuis le cache.
- Le filtrage se fait uniquement en PHP, après le chargement. Impossible de sélectionner en amont les plugins nécessaires.
3. Pas de hook pour modifier les définitions avant leur découverte
- Les hooks comme hook_plugin_filter_TYPE_alter ou hook_plugin_filter_TYPE__CONSUMER_alter interviennent trop tard : après la mise en cache ou le chargement.
- Conséquence : Vous ne pouvez pas limiter le nombre de définitions générées.
Pourquoi votre site ne plante pas (encore) ?
Le module block_content filtre intelligemment les blocs :
- Seuls les reusable blocks (blocs standard) sont retournés comme derivatives dans la méthode getDerivativeDefinitions().
- Les blocs créés via Layout Builder (non-reusable) sont exclus.
Voici comment dans la classe deriver des block content :
public function getDerivativeDefinitions($base_plugin_definition) {
$block_contents = $this->blockContentStorage->loadByProperties(['reusable' => TRUE]);
$this->derivatives = [];
foreach ($block_contents as $block_content) {
$this->derivatives[$block_content->uuid()] = $base_plugin_definition;
$this->derivatives[$block_content->uuid()]['admin_label'] = $block_content->label() ?? ($block_content->type->entity->label() . ': ' . $block_content->id());
$this->derivatives[$block_content->uuid()]['config_dependencies']['content'] = [
$block_content->getConfigDependencyName(),
];
}
return parent::getDerivativeDefinitions($base_plugin_definition);
}Une issue est en cours sur inline entity form pour cela mais reusable = FALSE implique également de considérer l'entité comme une "inline entity" ce qui, du point de vue du core, implique également d'implémenter l'API inline entity : https://www.drupal.org/project/inline_entity_form/issues/3002175.
Pas de solution miracle en vue
IOSAN a contribué à une étude et proposition de correctif a été étudiée avec les contributeurs du cœur, mais les effets de bord sur le système de plugins étaient trop risqués.
Conclusion : C’est aux modules contrib de gérer ce problème.
Recommandations : Comment éviter le désastre ?
Pour les Site Builders
Utilisez les modules pour ce pour quoi ils sont conçus :
- Ne créez jamais de champ inline entity reference permettant de générer des Block Content.
- Préférez des solutions dédiées (ex. : modules de Paragraphs ou Layout Builder avec des limites claires).
Pour les développeurs de modules
- Évitez les derivatives basés sur du contenu ou des configurations sans whitelist :
→ Exemple : Ne générez pas de plugins dynamiques à partir d’entités ou de configurations utilisateur. - Évitez les dérivation en cascade (ex. : derivative depuis un champ > un bundle > un view mode).
→ Risque : Croissance exponentielle du nombre de définitions (impossible à prédire). - Documentez les risques : Avertissez les utilisateurs dans la documentation.
- Implémentez hook_requirements() :
→ Exemple : Affichez un avertissement si le nombre de derivatives devient critique. - Privilégiez la configuration à la définition :
- Concevez vos plugins comme des "types" (ex. : field_type).
- Le plugin lui-même doit charger ses données en fonction de sa configuration, et non de sa définition.
→ Avantages : Meilleure performance, système plus ouvert et scalable.
En résumé : Les Derivative Plugins sont-ils à bannir ?
Non, mais à utiliser avec une extrême prudence :
✔ OK pour des cas contrôlés (ex. : quelques blocs réutilisables, dérivation depuis 1 seul niveau de config entity).
❌ JAMAIS pour des générations massives ou incontrôlées (ex. : basés sur des configs tierses, cascades, champs inline entity reference).
Partez sur la bonne trajectoire (ou revenez sur le droit chemin)
Que votre projet soit à l'étude ou déjà en production, IOSAN vous aide à rester sur les rails pour garantir sur votre projet restera performant, scalable et sécurisé sur le long terme.
Nous pouvons vous accompagner en amont sur la définition de l'architecture de contenu, sur les choix techniques.
Nous pouvons également effectuer un audit ciblé et vous proposer des solutions efficaces et adaptées à votre contexte.