Herb et ReactionView : Révolutionner le templating ERB dans Rails

Vous en avez marre de vos templates ERB qui ressemblent à un plat de spaghettis ? Vous rêvez d'avoir un vrai feedback quand votre HTML part en vrille ? Vous souhaitez enfin développez des applications avec React ET Rails de manière native?


Durant une des présentations de Rails World 2025, Marco Roth, développeur full-stack et contributeur open source passionné, a présenté LA solution qu'on attendait tous. Dans sa présentation, il dévoile Herb, un parser ERB conscient du HTML, et ReactionView, une initiative ambitieuse pour moderniser la couche vue de Rails sans abandonner ce qui fait la beauté du framework.


Dans cet article, vous allez découvrir comment ces outils peuvent transformer votre expérience de développement, du formatage automatique de vos templates jusqu'à la possibilité d'intégrer des composants React ou Vue directement dans vos vues Rails.

Accrochez-vous, ça va secouer votre workflow !

Le problème avec ERB aujourd'hui

Un parser qui ne comprend pas le HTML

Depuis 2004, ActionView n'a pratiquement pas changé. C'est stable, c'est fiable, mais... c'est aussi limité. Le moteur de templating actuel, eRuby, traite vos fichiers .erb comme de simples fichiers texte avec des bouts de Ruby saupoudrés dedans. Le problème ? Il n'a aucune conscience de la structure HTML.

Prenons un exemple concret. Si vous écrivez ce template :


<div>
<% if user.admin? %>
<p>Zone d'administration</p>
<% end %>


Un parser ERB classique voit ça :

  1. Un tag ERB (<% if ... %>)
  2. Du texte quelconque
  3. Un autre tag ERB (<% end %>)


Il ne comprend pas que le if et le end forment une structure logique englobant un élément HTML. C'est comme si vous donniez un livre à quelqu'un qui ne sait lire que les mots isolés, sans comprendre les phrases !

Les conséquences au quotidien

Cette limitation se traduit par plusieurs frustrations :


  1. Pas d'autocomplétion intelligente : Votre éditeur ne peut pas vous aider à compléter les attributs data-controller ou data-action de Stimulus
  2. Détection d'erreurs inexistante : Vous oubliez une balise fermante ? Vous ne le saurez qu'en ouvrant la page dans votre navigateur
  3. Formatage impossible : Essayez de formater automatiquement un fichier ERB complexe avec Prettier... spoiler : ça ne marchera pas
  4. Tooling limité : Les outils comme les linters ne fonctionnent que sur le HTML pur, pas sur les tag helpers Rails (tag.div, content_tag, etc.)


Pour rappel un linter est un outil qui analyse ton code pour détecter les erreurs, les incohérences et les mauvaises pratiques. Il t’aide à garder un style de code propre, cohérent et plus facile à maintenir. En gros, c’est comme un correcteur orthographique, mais pour les développeurs.

Herb : Un parser ERB qui comprend le HTML

L'architecture d'Herb

Herb (HTML-aware ERB Parser) est la réponse à tous ces problèmes. C'est un écosystème complet d'outils construit autour d'un parser nouvelle génération.

Voici ses caractéristiques techniques :

  1. Écrit en C : Pour des performances maximales
  2. Basé sur Prism : Le nouveau parser Ruby officiel, pour analyser le code Ruby dans vos templates
  3. Multi-plateforme : Fonctionne dans Ruby (extension C), Node.js, JavaScript et même dans le navigateur


Ce qui rend Herb spécial, c'est qu'il produit un arbre syntaxique entrelacé (interleaved syntax tree) du HTML et du Ruby. Contrairement à eRuby qui voit des morceaux déconnectés, Herb comprend la hiérarchie complète.

Exemple concret de parsing

Reprenons notre exemple précédent :


<div>
<% if user.admin? %>
<p>Zone d'administration</p>
<% end %>
</div>

Avec Herb, le parser produit une structure comme celle-ci :


HTMLElementNode
├─ OpeningTag: <div>
├─ Body:
│ ├─ ERBTag (if): <% if user.admin? %>
│ ├─ HTMLElementNode: <p>Zone d'administration</p>
│ └─ ERBTag (end): <% end %>
└─ ClosingTag: </div>


Herb sait que le if et le end sont liés. Il sait que l'élément <p> est à l'intérieur du bloc conditionnel. Cette compréhension structurelle ouvre des possibilités infinies.

Les outils de l'écosystème Herb

Le formateur automatique

Le premier outil révolutionnaire, c'est Herb Formatter. (Oui, un formateur qui fonctionne vraiment pour ERB ! Non, vous ne rêvez pas.)


Vous écrivez du code bordélique ? Vous sauvegardez le fichier, et PAF ! Le code se reformate automatiquement avec une indentation correcte, des espacements cohérents. Et ça fonctionne aussi bien sur le HTML pur que sur les tag helpers Rails.


<!-- Avant -->
<div><% if user %><%=user.name%><% end %></div>
<!-- Après formatage automatique -->
<div>
<% if user %>
<%= user.name %>
<% end %>
</div>

Le linter intelligent

Herb Lint embarque actuellement 32 règles pour détecter les erreurs courantes et imposer les bonnes pratiques. Voici quelques exemples :

  1. Détection des IDs dupliqués : Herb sait si vous utilisez le même id deux fois dans votre page (ce qui est invalide en HTML)
  2. 9 règles d'accessibilité : Pour vous assurer que votre HTML est utilisable par tous
  3. Validation de structure : Détection de balises mal fermées, d'imbrications invalides (comme des balises <p> dans des <p>)


Tout ça avec une sortie CLI magnifiquement colorée qui vous montre exactement où se trouve le problème.

Stimulus Lint : enfin des diagnostics pour Stimulus !

Stimulus Lint est un package spécifique qui extrait les diagnostics du Stimulus LSP (Language Server Protocol). Avant, ces vérifications n'étaient disponibles que dans l'éditeur. Maintenant, vous pouvez les exécuter dans votre CI/CD !

Le package utilise le Stimulus Parser et Herb pour détecter :

  1. Les contrôleurs Stimulus non définis
  2. Les actions référençant des méthodes inexistantes
  3. Les targets invalides


Ils prévoient également de développer un linter pour Turbo à l'avenir !

Tailwind Pretty : le tri automatique des classes

Si vous utilisez Tailwind CSS (et soyons honnêtes, qui ne l'utilise pas en 2025 ?), vous allez adorer Tailwind Pretty Plugin. C'est l'équivalent du plugin officiel Prettier de Tailwind, mais qui fonctionne avec Herb.

Quand vous ajoutez des classes Tailwind à vos éléments HTML et sauvegardez, elles se réorganisent automatiquement selon l'ordre recommandé par la documentation Tailwind. Et ça marche aussi sur les tag helpers Rails !


<!-- Avant -->
<div class="p-4 bg-blue-500 text-white rounded">
<!-- Après tri automatique -->
<div class="rounded bg-blue-500 p-4 text-white">

ReactionView : Réinventer le moteur de rendu Rails

Le constat de départ

Après avoir construit tous ces outils de parsing, Marco s'est posé une question vertigineuse : Et si on utilisait Herb pour créer un nouveau moteur de rendu pour Rails ?


Le moteur actuel (eRuby/Erubi) compile vos templates en utilisant des expressions régulières. Il découpe le template en morceaux de texte et de Ruby, puis les concatène dans un buffer. C'est simple, mais ça ne tire aucun profit de la structure du document.

Comment fonctionne le moteur Herb

Le moteur de rendu Herb fonctionne différemment. Voici le processus :

  1. Parsing : Le template est transformé en arbre syntaxique
  2. Visite de l'arbre : Un "visitor" parcourt chaque nœud (éléments HTML, tags ERB, texte)
  3. Compilation optimisée : Les nœuds consécutifs de même type sont fusionnés avant compilation
  4. Génération de code : On produit un template compilé similaire à celui d'Erubi, mais avec la garantie d'un HTML valide


Le résultat ? Un moteur compatible avec l'API d'Erubi, que vous pouvez brancher dans Rails sans modifier votre code existant.

Validation HTML automatique

La communauté avait BESOIN de ce nouveau moteur. Qui n'a pas déjà passé un temps beaucoup trop long à essayer de comprendre d'où venait l'erreur dans sa vue HTML ?


Prenons l'exemple ci-dessous où il nous manque des valises de fermetures


<div>
<p>Contenu
```


Rails va compiler ce code sans broncher. Il s'en fiche que la balise `<p>` ne soit pas fermée. Vous ne découvrirez l'erreur que plus tard, en inspectant le HTML généré.


Avec Herb ? Boom! Erreur de compilation immédiate


```
Template compilation error: Unclosed <p> tag
```


Herb refuse de compiler du HTML invalide. C'est comme passer d'un langage dynamiquement typé à un langage avec vérification statique des types, mais pour vos templates.


De plus puisque HERB sait décomposer les noeuds HTML de manière précise et il peut donc trouver exactement où se trouve l'erreur dans votre vue vous faisant économiser pas mal de points de santé mentale.


Syntax error in app/views/users/show.html.erb:15:3
13 | <div class="profile">
14 | <%= user.name %>
15 | <p><p>Email: <%= user.email %></p>
| ^ Invalid nested <p> tags
16 | </div>


La ligne exacte, la colonne exacte, avec une petite flèche qui pointe sur le problème et un petit message explicite. Fini de chercher pendant 10 minutes une balise mal fermée !

Les fonctionnalités de debug révolutionnaires

Annotations visuelles des templates

ActionView a une config appelée annotate_rendered_view_with_filenames qui ajoute des commentaires HTML autour de vos partials.

Bon super mais quand on a beaucoup de partial ce n'est pas vraiment si pratique. Le problème ? On ne peut pas styler des commentaires HTML.


Herb fait mieux : il injecte des attributs data-* sur vos éléments en développement. Combiné à un peu de CSS, vous obtenez des outlines colorées autour de chaque vue, partial et composant.

  1. Bleu pour les vues principales
  2. Vert pour les partials
  3. Violet pour les composant


Au survol, le chemin complet du fichier apparaît. Et tenez-vous bien : en cliquant sur l'outline, le fichier s'ouvre directement dans votre éditeur ! C'est comme avoir des devtools qui communiquent directement avec votre IDE.


Ajouté la balise de debug

<html data-herb-debug-file-name="application.html.erb">
...
</html>


Plus un peu de CSS


[data-herb-debug-file-name] {
outline: #3B82F6 dotted 2px;
outline-offset: 2px;
}


Vous obtenez une vue claire et stylisée où vous avez une bordure stylisée sur vos éléments. Pratique non ? :)

Visualisation du contenu dynamique

Encore mieux ! Vous pouvez ajouter un type


<html
data-herb-debug-outline-type="view"
data-herb-debug-file-name="application.html.erb"
>
...
</html>


Cela vous permet sur une page avec beaucoup de composants de les visualiser directement.

Et si vous leur ajouté un attribut "path", au survol vous voyez la valeur rendue. En cliquant, vous sautez directement au fichier et à la ligne où cette expression est définie. Plus besoin de faire du grep dans toute votre codebase pour retrouver d'où vient ce mystérieux bout de texte !


<html
data-herb-debug-outline-type="view"
data-herb-debug-file-name="application.html.erb"
data-herb-debug-file-relative-path="..."
data-herb-debug-file-full-path="..."
>
...
</html>


Installation et utilisation

Premiers pas

Pour tester Herb dans votre application Rails, c'est ridiculement simple :


bundle add reactionview
rails generate reactionview:install


Le générateur crée un initializer. Pour activer l'interception des templates ERB :


# config/initializers/reactionview.rb
ReactionView.configure do |config|
config.intercept_erb = true
end


Redémarrez votre serveur, et voilà ! Vous avez maintenant :

  1. Des messages d'erreur précis
  2. Les annotations visuelles de templates
  3. La visualisation du contenu dynamique
  4. La validation HTML automatique

Utiliser les outils en ligne de commande

Pour le formatage :


herb format app/views/**/*.html.erb


Pour le linting :


herb lint app/views/**/*.html.erb


C'est aussi simple que ça !

La vision ReactionView : Combler le fossé

Le problème de l'écart SPA vs SSR


Marco identifie un problème fondamental dans l'écosystème Rails aujourd'hui : il n'y a pas de terrain d'entente entre une application Rails classique avec Hotwire (rendu côté serveur) et une SPA complète avec une API Rails.



Quand une équipe veut plus d'interactivité, plus de contrôle, elle abandonne souvent tout et part sur une SPA. C'est tout ou rien. Marco veut créer des paliers intermédiaires, des niveaux d'adoption progressifs.

Les 6 niveaux d'adoption prévus

ReactionView définit 6 niveaux pour faire évoluer progressivement votre application :


Niveau 1 & 2 (disponibles aujourd'hui avec Herb 0.7) :

  1. Moteur de rendu HTML-aware
  2. Validation automatique du HTML
  3. Messages d'erreur précis
  4. Annotations visuelles de debug

Niveau 3 (en exploration) :

  1. Optimisations internes d'ActionView
  2. Inlining des appels de partials
  3. Rendu optimisé des tag helpers
  4. Performances accrues

Niveau 4 (inspiration Phoenix LiveView) :

  1. Diffing intelligent : Ne re-rendre que les parties qui ont changé
  2. Tracking de l'état avant/après
  3. Rendu sélectif par élément

Niveau 5 (composants hybrides) :

  1. Possibilité d'utiliser des composants React, Vue ou Svelte directement dans ERB
  2. Hydratation automatique côté client
  3. Passage de props depuis le serveur
  4. Enregistrement de bibliothèques externes (comme shadcn/ui)

Imaginez pouvoir écrire ça :


<div>
<h1>Ma page Rails</h1>
<!-- Un composant React externe -->
<ReactDatePicker selected={@date} onChange={@handle_date_change} />
<!-- Du bon vieux HTML Rails -->
<%= render @posts %>
</div>


Niveau 6 (vision ultime) :

  1. Composants serveur pouvant être transférés côté client (l'inverse des React Server Components !)
  2. CSS scopé par composant (comme dans Vue.js avec <style scoped>)
  3. JavaScript scopé par vue (comme Svelte)
  4. Mises à jour optimistes de l'UI
  5. Fonctionnement offline amélioré

Exemple de CSS scopé

Une des idées explorées, c'est le CSS scopé par fichier de vue, inspiré de Vue.js :


<!-- app/views/users/card.html.erb -->
<div class="user-card">
<%= user.name %>
</div>


<style scoped>
.user-card {
border: 1px solid #ccc;
padding: 1rem;
}
</style>


Le moteur transformerait ça en ajoutant des attributs data-* uniques :

<div class="user-card" data-erb-scope="user-card-abc123">
John Doe
</div>


<style>
.user-card[data-erb-scope="user-card-abc123"] {
border: 1px solid #ccc;
padding: 1rem;
}
</style>


Résultat : vos styles ne fuient jamais en dehors du composant. Adieu les conflits de classes CSS ! Moi je dis un grand oui parce que le debug de CSS ça va bien 5 min.

Pourquoi c'est important pour Rails

Garder Rails attractif et moderne

Marco est très clair sur sa motivation : Rails doit rester attractif pour les nouveaux projets. Trop d'équipes choisissent aujourd'hui de partir directement sur des SPAs parce qu'elles pensent qu'ActionView n'est pas assez puissant.

Mais abandonner ActionView, c'est perdre :

  1. La productivité incroyable de Rails
  2. Le rendu côté serveur (meilleur pour le SEO)
  3. La simplicité de ne pas gérer un état client complexe
  4. L'intégration naturelle avec Active Record et le reste du framework

ReactionView vise à prouver qu'on peut avoir le beurre et l'argent du beurre : la simplicité de Rails ET la puissance d'interactivité des frameworks modernes.

Embrasser les standards web modernes

La plateforme web a énormément évolué ces dernières années :

  1. Web Components pour créer des éléments réutilisables
  2. Import Maps pour charger des modules ES6
  3. View Transitions API pour des animations fluides entre pages
  4. Popover API et Invoker Commands pour de l'interactivité sans JavaScript
  5. Container Queries, CSS Nesting et CSS Functions en CSS

Rails ne devrait pas ignorer ces avancées. ReactionView propose de les intégrer naturellement dans le workflow Rails.

Une approche incrémentale

Le génie de ReactionView, c'est qu'il ne casse rien. Le moteur Herb est 100% compatible avec Erubi. Vous pouvez l'activer dans votre application existante sans changer une ligne de code. C'est du drop-in replacement parfait.

Et si quelque chose ne fonctionne pas ? Vous désactivez l'option et vous revenez au moteur classique. Pas de migration douloureuse, pas de refactoring géant.

L'impact de Prism et l'effet domino

La révolution Prism pour Ruby

Marco fait un parallèle intéressant avec Prism, le nouveau parser Ruby officiel. Prism a révolutionné l'outillage Ruby en offrant un AST (Abstract Syntax Tree) standardisé et performant. Cela a permis l'émergence d'outils comme le Ruby LSP, qui améliore drastiquement l'expérience développeur dans les éditeurs.

Le même effet pour les templates

Herb vise à avoir le même impact pour les templates ERB :

  1. Un AST standardisé du HTML + ERB
  2. Une base commune pour construire des outils
  3. Des performances élevées (grâce au C)
  4. Une adoption facilitée par la compatibilité

L'idée, c'est que d'autres projets puissent construire sur Herb, de la même manière qu'ils construisent sur Prism aujourd'hui.

Limitations et prochaines étapes

État actuel du projet

Soyons honnêtes : ReactionView est encore expérimental. Marco le présente comme une "vision talk", une exploration de ce qui est possible. Les niveaux 1 et 2 sont prêts pour les tests, mais les niveaux supérieurs sont encore en phase de recherche.

Comment contribuer

Le projet est open source et Marco encourage activement la communauté à :

  1. Tester Herb dans vos applications : C'est en production qu'on trouve les vrais bugs
  2. Signaler les problèmes : Ouvrez des issues sur GitHub si quelque chose ne fonctionne pas comme attendu
  3. Contribuer du code : Le projet accepte les pull requests
  4. Partager vos retours : Même si c'est juste "ça marche super bien" ou "je ne vois pas l'intérêt", les retours sont précieux
  5. Donner une étoile sur GitHub : Pour donner de la visibilité au projet

Liens utiles

  1. Herb sur GitHub
  2. Documentation Herb
  3. ReactionView sur GitHub

Conclusion : L'avenir de la couche vue Rails

ReactionView n'est peut-être qu'une vision aujourd'hui, mais c'est une vision nécessaire. Le paysage du développement web a changé, les attentes ont évolué, et Rails doit s'adapter sans perdre son âme.

Herb et ReactionView montrent qu'il est possible de moderniser ActionView en restant fidèle aux principes de Rails :

  1. Convention over configuration
  2. De bons defaults
  3. La simplicité avant tout
  4. Mais avec la puissance quand on en a besoin


Marco Roth et les contributeurs d'Herb ont déjà accompli quelque chose de remarquable : prouver que l'outillage pour les templates peut être aussi bon que pour le code Ruby. Les annotations visuelles, le formatage automatique, la validation HTML... ce sont des fonctionnalités qu'on attendait depuis des années.

Alors oui, installer reactionview, activer intercept_erb = true, et voir vos erreurs de template enfin présentées clairement, c'est peut-être un petit pas. Mais c'est un pas dans la bonne direction : celle d'un Rails moderne, puissant, et toujours aussi agréable à utiliser.


La communauté Ruby a construit des outils incroyables pour le langage lui-même. Il est temps d'apporter le même soin à la couche vue. Et avec Herb, nous en avons enfin les moyens. 🚀


Retrouvez la présentation complète de Marco ci-dessous :





Share it: