vendredi 25 septembre 2026

À propos

Contact

Blocs Gutenberg

Un plugin désactivé casse silencieusement douze blocs liés

Une dépendance cachée entre blocs de plugins différents, découverte seulement après la désactivation d'une extension en production.

Par Clément Hadrot • 19 mai 2026 • 4 min de lecture • Aucun commentaire
Un plugin désactivé casse silencieusement douze blocs liés

Le Cabinet Ferrand a désactivé, en production et sans préavis particulier, une extension de gestion de rendez-vous jugée obsolète après le passage à un nouvel outil de prise de rendez-vous en ligne. L’opération semblait sans risque : plus aucune page n’utilisait le bloc de prise de rendez-vous fourni par cette extension depuis des mois. Dans l’heure qui a suivi, douze blocs répartis sur plusieurs pages du site ont cessé de s’afficher correctement, sans lien apparent avec la fonctionnalité de rendez-vous elle-même.

Symptôme : une panne qui ne pointe pas vers sa cause

Les blocs affectés appartenaient à trois extensions différentes, aucune n’étant celle qui venait d’être désactivée. Leur point commun, invisible à première vue : tous consommaient, via useSelect, un store de données personnalisé (createReduxStore) enregistré par l’extension de rendez-vous, pour vérifier une disponibilité générique avant d’afficher certains éléments d’interface (un badge « sur rendez-vous » affiché sur des fiches services, des articles, et une page d’équipe).

Diagnostic : une dépendance de fait, jamais déclarée

Aucun des block.json des blocs affectés ne mentionnait l’extension de rendez-vous dans un champ de dépendance quelconque, pour une raison simple : ce lien avait été ajouté après coup, par un développeur différent, sur un projet différent, sans jamais documenter cette dépendance croisée. Le store cabinet-ferrand/rendez-vous était simplement supposé toujours présent, car il l’avait toujours été jusque-là.

// Dans un bloc totalement différent, sans lien apparent :
const disponibilite = useSelect(
  (select) => select('cabinet-ferrand/rendez-vous')?.getDisponibiliteGenerale(),
  []
);
L'essentiel à retenir : Un bloc peut consommer discrètement le store d'un autre plugin ; Le champ requires de la clé Plugin Dependencies ne couvre pas toute dépendance ; Documenter les dépendances inter-plugins avant toute désactivation

Une fois l’extension désactivée, select('cabinet-ferrand/rendez-vous') retournait undefined, provoquant une erreur JavaScript non interceptée (« Cannot read properties of undefined ») au moment d’appeler .getDisponibiliteGenerale(), qui faisait planter le rendu de tout le composant React englobant, pas seulement le badge concerné.

Ce que la clé Plugin Dependencies ne couvre pas

La fonctionnalité « Plugin Dependencies », introduite avec le champ Requires Plugins dans l’en-tête d’un plugin, permet de déclarer qu’une extension a besoin d’une autre pour s’activer, avec un message d’avertissement dans l’administration si la dépendance est manquante. Ce mécanisme couvre les dépendances déclarées au niveau du plugin entier, mais ne protège en rien contre une dépendance de fait entre un bloc précis et un store de données précis, ajoutée après coup sans mise à jour de cet en-tête.

Correctifs mis en place

  1. Vérification défensive systématique avant tout appel à un sélecteur d’un store externe, avec un repli explicite plutôt qu’un plantage silencieux :
const store = select('cabinet-ferrand/rendez-vous');
const disponibilite = store?.getDisponibiliteGenerale?.() ?? null;

if (disponibilite === null) {
  return null; // Le badge ne s'affiche simplement pas, sans erreur.
}
  1. Mise à jour de l’en-tête Requires Plugins de chaque extension concernée, pour au moins avertir dans l’administration en cas de désactivation future de l’extension dont dépendent ces blocs.
  2. Un document de dépendances inter-plugins, tenu à jour manuellement, recensant tout store ou fonction PHP partagé entre extensions distinctes du même site, un filet qu’aucun mécanisme natif de WordPress ne fournit à ce niveau de granularité.
  • Ne jamais supposer qu’un store de données externe est toujours présent, même si c’est vrai depuis des mois.
  • Toujours prévoir un repli silencieux plutôt qu’un plantage quand un store ou une fonction externe peut être absente.
  • Tester la désactivation de chaque extension en environnement de recette avant toute désactivation en production, même pour une extension jugée obsolète.

Une dépendance qui n’est écrite nulle part existe quand même : elle attend simplement le jour où quelqu’un désactivera l’extension qui la porte.

Ce que ce cas ne couvre pas

Les conflits d’extensions au sens large (collision de scripts, de styles, de hooks concurrents) relèvent d’une problématique plus générale déjà traitée ailleurs. Ce retour d’expérience se concentre spécifiquement sur la dépendance cachée entre blocs de plugins différents via un store de données partagé.

Notre verdict

Douze blocs affectés par la désactivation d’une seule extension jugée sans lien : l’incident a coûté au Cabinet Ferrand une soirée de correctif d’urgence, et surtout a révélé que documenter les dépendances entre plugins d’un même site n’est pas un luxe réservé aux gros projets.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi