Des templates qui se compilent en simples fonctions
Verso transforme un template en fonction JavaScript au moment du build. Pas de DOM virtuel, pas de dépendance à l’exécution, aucun parseur envoyé au client — juste une fonction qui prend des données et renvoie une chaîne.
<!-- greeting.vs -->
<section class="cards">
{{#each items as item, i}}
<article data-index="{{i}}">
<h3>{{item.title}}</h3>
{{#if item.note}}
<p>{{item.note | truncate: 120}}</p>
{{/if}}
</article>
{{#else}}
<p>Nothing here yet.</p>
{{/each}}
</section>
Pensé pour ceux qui génèrent du HTML côté serveur
Verso est né en 2021 : un fichier de 300 lignes dans une chaîne de production de contenu qui avait dépassé la concaténation de chaînes et ne voulait pas de framework. Il reste volontairement petit.
Compilé, pas interprété
Chaque template devient une fonction autonome, sans fermeture sur le moteur. Générer un tableau de 2 000 lignes prend 1,9 ms sur un portable de 2019 — à peu près le coût de l’allocation de la chaîne elle-même.
Rien en dessous
Aucune dépendance à l’exécution et trois dépendances de développement au total. Le paquet entier tient en quatre fichiers, et npm ls sur une installation neuve n’affiche qu’une ligne.
Streaming par défaut
renderToStream() envoie chaque bloc de premier niveau dès qu’il est prêt : une requête lente en base ne retarde qu’une section, pas toute la page.
Échappement par défaut
Chaque interpolation est échappée en HTML, sauf si vous y renoncez explicitement avec {{{ }}}. L’échappement tient compte du contexte des attributs, des URL et des styles en ligne.
Des erreurs lisibles
Les erreurs de compilation indiquent le chemin du template, la ligne, la colonne et un caret sous le jeton fautif. Les erreurs d’exécution conservent le cadre du template dans la pile d’appels.
Stable par principe
Un seul changement incompatible en quatre ans, annoncé six mois à l’avance. La branche 2.x reçoit encore des correctifs de sécurité jusqu’en juin 2027.
Trente secondes jusqu’au premier rendu
# npm, pnpm or yarn — all the same package
$ npm install verso
# or try it without installing
$ npx verso render greeting.vs --data data.json
Nécessite Node.js 18 ou plus récent. La version navigateur est publiée sous verso/browser et ne contient que les fonctions d’exécution — le compilateur reste sur votre machine de build.
import { compileFile } from 'verso';
const page = await compileFile('./views/page.vs');
server.get('/', async (req, res) => {
res.type('html').send(page({
title: 'Release notes',
items: await db.releases(20)
}));
});
Mesuré, pas affirmé
Les benchmarks tournent sous Node 22.11, Apple M1, 50 itérations après 20 tours de chauffe. La suite est dans bench/ et la sortie brute est versionnée à chaque release.
Comment un template devient une fonction
1 · Analyse
Un scanner en une seule passe produit une liste plate de jetons. Aucun retour arrière d’expression régulière dans le parseur : un template mal formé échoue en temps linéaire au lieu de bloquer.
2 · Construction
Les jetons deviennent un petit arbre de nœuds. Les sous-arbres constants — HTML statique, attributs littéraux — sont fusionnés à ce stade en simples blocs de texte.
3 · Émission
L’arbre est imprimé en code JavaScript et passé à new Function, ou écrit sur disque par la CLI quand vous voulez l’inspecter ou l’empaqueter.
Discrètement, à quelques endroits
Verso n’est pas un projet populaire et ne cherche pas à l’être. Il est téléchargé environ 40 000 fois par mois, surtout par les mêmes chaînes de build, et c’est une taille que nous pouvons maintenir honnêtement.
Si vous hésitez avec quelque chose de plus gros : choisissez Verso quand vous générez du HTML côté serveur, voulez pouvoir lire tout le moteur en un après-midi et préférez ne pas auditer un arbre de dépendances. Choisissez autre chose si vous avez besoin de réactivité côté client — Verso n’a pas d’avis sur le DOM et n’en aura jamais.