# Pourquoi save() et render_callback ont longtemps cohabité dans un bloc

> Un même bloc, un contenu servi par save() côté front puis remplacé par render_callback : cette cohabitation, source de confusion pour les nouveaux venus, a une explication précise.

- Auteur : WordPress Développement
- Publié le : 2023-12-26
- Mis à jour le : 2023-12-26
- Catégorie : Blocs Gutenberg
- URL : https://www.wpmoderne.fr/blocs/save-et-render-callback-cohabitation-historique/

## L’essentiel

- save() sert de secours et de format d'échange, pas de rendu final
- render_callback prend le dessus dès qu'il est déclaré
- Comprendre cette hiérarchie évite des heures d'incompréhension

Depuis l'arrivée de l'éditeur de blocs en 2018, deux mécanismes de rendu coexistent pour un même bloc dynamique, ce qui laisse perplexe quiconque découvre pour la première fois un tutoriel un peu ancien : la fonction JavaScript `save()` semble définir le rendu final, alors qu'un fichier PHP `render_callback` vient ensuite le remplacer entièrement. Comprendre pourquoi ces deux mécanismes cohabitent éclaire une bonne partie des vieux tutoriels qui mélangent les deux approches sans toujours l'expliquer.

## Le rôle réel de save() pour un bloc dynamique

Pour un bloc statique, `save()` définit directement le balisage HTML qui sera stocké tel quel dans le contenu de l'article, entre les commentaires de bloc (`<!-- wp:mon-bloc -->`). Pour un bloc dynamique, en revanche, `save()` ne sert plus à produire le rendu final affiché aux visiteurs : son rôle se limite à définir ce qui sera sérialisé dans la base de données, souvent réduit à `null` ou à un balisage minimal servant de secours en cas de désactivation de l'extension qui enregistre le bloc.

## Le rôle de render_callback

Lorsqu'un bloc est enregistré côté PHP avec un `render_callback` (ou, plus récemment, une clé `render` dans `block.json` pointant vers un fichier de rendu), cette fonction prend systématiquement le dessus sur le contenu sérialisé par `save()` au moment d'afficher la page : WordPress ignore le balisage stocké et exécute la fonction PHP à chaque affichage, en lui passant les attributs désérialisés du bloc. C'est ce mécanisme qui permet à un bloc d'afficher une donnée toujours à jour (une liste d'articles récents, une météo, un compteur) plutôt qu'un instantané figé au moment de la rédaction.

> L'essentiel à retenir : save() sert de secours et de format d'échange, pas de rendu final ; render_callback prend le dessus dès qu'il est déclaré ; Comprendre cette hiérarchie évite des heures d'incompréhension

## Pourquoi ne pas avoir supprimé save() pour ces blocs

Trois raisons expliquent le maintien de `save()` même pour un bloc entièrement dynamique. D'abord, le format de sérialisation du contenu WordPress repose sur des commentaires HTML qui encadrent une trace du bloc dans la base ; sans un minimum de balisage, la récupération de secours en cas de désactivation de l'extension deviendrait impossible, laissant un vide silencieux là où le bloc était affiché. Ensuite, les outils tiers qui analysent le contenu (recherche, export, certains plugins de cache) s'appuient parfois sur cette trace HTML minimale pour repérer la présence du bloc, sans exécuter de PHP. Enfin, la validation du contenu par l'éditeur, qui compare le rendu attendu au contenu stocké pour détecter une éventuelle corruption, a besoin d'une référence stable, même minimale, pour les blocs qui en fournissent une.

### Le cas des tutoriels anciens

De nombreux tutoriels publiés autour de 2018 et 2019, période où les bonnes pratiques autour des blocs entièrement dynamiques n'étaient pas encore stabilisées, montrent des blocs où `save()` reproduit une partie significative du rendu, dans l'idée de fournir un affichage minimal même sans PHP actif. Cette pratique a progressivement cédé la place à un usage plus strict de `save()` réduit à `null`, à mesure que la communauté a affiné sa compréhension du mécanisme et de ses pièges.

- `save()` retourne `null` : convention actuelle pour un bloc entièrement dynamique, la plus simple à maintenir.
- `save()` retourne un balisage réduit : utile comme filet de sécurité en cas de désactivation de l'extension.
- `save()` qui duplique tout le rendu final : pratique héritée des débuts, aujourd'hui source de confusion et de désynchronisation.

## Un piège concret de cette cohabitation

Quand `save()` reproduit une partie du rendu et que `render_callback` évolue de son côté sans que `save()` ne soit mis à jour en parallèle, l'aperçu affiché dans l'éditeur (basé sur `save()` pour un bloc sans `ServerSideRender`) diverge silencieusement du rendu réel du site. C'est l'une des raisons pour lesquelles un bloc entièrement dynamique gagne à réduire `save()` au strict minimum et à s'appuyer sur `ServerSideRender` pour l'aperçu dans l'éditeur, plutôt que de maintenir deux logiques de rendu en parallèle.

## En résumé

La cohabitation entre `save()` et `render_callback` n'est pas une incohérence de l'éditeur de blocs, mais le reflet d'un besoin de secours et de compatibilité qui existe depuis l'introduction de ce système en 2018. Pour un bloc conçu aujourd'hui, la règle la plus simple reste de réduire `save()` à sa plus stricte expression et de laisser `render_callback`, ou la clé `render` de `block.json`, porter seul la responsabilité du rendu affiché aux visiteurs.
