Templates die compileren naar gewone functies
Verso maakt van een template tijdens de build een JavaScript-functie. Geen virtuele DOM, geen runtime-afhankelijkheden, geen parser naar de client — alleen een functie die data krijgt en een string teruggeeft.
<!-- 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>
Gemaakt voor wie HTML op een server rendert
Verso begon in 2021 als een bestand van 300 regels in een contentpipeline die stringconcatenatie was ontgroeid en geen framework wilde. Het is nog steeds bewust klein.
Gecompileerd, niet geïnterpreteerd
Elk template wordt een losse functie zonder closure over de engine. Een tabel van 2 000 rijen renderen kost 1,9 ms op een laptop uit 2019 — ongeveer wat de stringallocatie zelf kost.
Niets eronder
Geen afhankelijkheden tijdens runtime en in totaal drie ontwikkelafhankelijkheden. Het hele pakket bestaat uit vier bestanden, en npm ls toont na een verse installatie één regel.
Streamt standaard
renderToStream() stuurt elk blok op het hoogste niveau door zodra het klaar is, zodat een trage databaseaanroep één sectie vertraagt in plaats van de hele pagina.
Escapet standaard
Elke interpolatie wordt HTML-geëscapet, tenzij je er bewust voor kiest dat niet te doen met {{{ }}}. Escaping houdt rekening met de context van attributen, URL’s en inline stijlen.
Leesbare fouten
Compileerfouten bevatten het templatepad, de regel, de kolom en een caret onder het foute token. Runtimefouten behouden het templateframe in de stacktrace.
Bewust stabiel
Eén brekende wijziging in vier jaar, zes maanden van tevoren aangekondigd. De 2.x-lijn krijgt nog tot juni 2027 beveiligingsfixes.
Dertig seconden tot de eerste render
# npm, pnpm or yarn — all the same package
$ npm install verso
# or try it without installing
$ npx verso render greeting.vs --data data.json
Vereist Node.js 18 of nieuwer. De browserbuild heet verso/browser en bevat alleen de runtime-helpers — de compiler blijft op je buildmachine.
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)
}));
});
Gemeten, niet beweerd
Benchmarks draaien op Node 22.11, Apple M1, 50 iteraties na 20 opwarmrondes. De suite staat in bench/ en de ruwe uitvoer wordt bij elke release meegecommit.
Hoe een template een functie wordt
1 · Parsen
Een scanner met één doorgang maakt een platte lijst tokens. Nergens in de parser zit backtracking van reguliere expressies, dus een kapot template faalt in lineaire tijd in plaats van te blijven hangen.
2 · Bouwen
Tokens worden een kleine boom van knooppunten. Constante deelbomen — statische HTML, letterlijke attributen — worden op dit punt samengevouwen tot losse stringstukken.
3 · Uitvoeren
De boom wordt als JavaScript-broncode geschreven en aan new Function doorgegeven, of door de CLI naar schijf geschreven als je hem wilt bekijken of bundelen.
Stilletjes, op een paar plekken
Verso is geen populair project en probeert dat ook niet te zijn. Het wordt zo’n 40 000 keer per maand gedownload, vooral door dezelfde buildpipelines, en dat is een omvang die we eerlijk kunnen onderhouden.
Twijfel je tussen Verso en iets groters? Kies Verso als je HTML op een server rendert, de hele engine in een middag wilt kunnen lezen en geen afhankelijkheidsboom wilt doorlichten. Kies iets anders als je reactiviteit aan clientzijde nodig hebt — Verso heeft geen mening over de DOM en krijgt die ook nooit.