Szablony, które kompilują się do zwykłych funkcji
Verso zamienia szablon w funkcję JavaScriptu na etapie budowania. Bez wirtualnego DOM, bez zależności w czasie działania, bez parsera wysyłanego do klienta — tylko funkcja, która przyjmuje dane i zwraca łańcuch znaków.
<!-- 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>
Dla tych, którzy renderują HTML na serwerze
Verso powstało w 2021 roku jako plik na 300 linii w potoku treści, który wyrósł z łączenia napisów i nie chciał frameworka. Wciąż jest celowo małe.
Kompilowane, nie interpretowane
Każdy szablon staje się samodzielną funkcją bez domknięcia nad silnikiem. Wyrenderowanie tabeli z 2 000 wierszy zajmuje 1,9 ms na laptopie z 2019 roku — mniej więcej tyle, co samo przydzielenie łańcucha.
Nic pod spodem
Zero zależności w czasie działania i łącznie trzy zależności deweloperskie. Cały pakiet to cztery pliki, a npm ls po świeżej instalacji wypisuje jedną linię.
Domyślnie strumieniowo
renderToStream() wysyła każdy blok najwyższego poziomu, gdy tylko jest gotowy, więc wolne zapytanie do bazy opóźnia jedną sekcję, a nie całą stronę.
Domyślnie escapuje
Każda interpolacja jest escapowana jako HTML, chyba że świadomie z tego zrezygnujesz za pomocą {{{ }}}. Escapowanie uwzględnia kontekst atrybutów, adresów URL i stylów inline.
Czytelne błędy
Błędy kompilacji zawierają ścieżkę szablonu, wiersz, kolumnę i znacznik pod błędnym tokenem. Błędy wykonania zachowują ramkę szablonu w stosie wywołań.
Stabilne z założenia
Jedna niekompatybilna zmiana w cztery lata, ogłoszona pół roku wcześniej. Linia 2.x dostaje poprawki bezpieczeństwa do czerwca 2027.
Trzydzieści sekund do pierwszego renderu
# npm, pnpm or yarn — all the same package
$ npm install verso
# or try it without installing
$ npx verso render greeting.vs --data data.json
Wymaga Node.js 18 lub nowszego. Wersja przeglądarkowa jest opublikowana jako verso/browser i zawiera tylko funkcje pomocnicze środowiska wykonania — kompilator zostaje na maszynie budującej.
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)
}));
});
Zmierzone, nie zadeklarowane
Benchmarki działają na Node 22.11, Apple M1, 50 iteracji po 20 rundach rozgrzewki. Zestaw jest w bench/, a surowe wyniki trafiają do repozytorium z każdym wydaniem.
Jak szablon staje się funkcją
1 · Parsowanie
Jednoprzebiegowy skaner tworzy płaską listę tokenów. W parserze nigdzie nie ma nawrotów wyrażeń regularnych, więc wadliwy szablon kończy się błędem w czasie liniowym, zamiast się zawiesić.
2 · Budowanie
Tokeny stają się małym drzewem węzłów. Stałe poddrzewa — statyczny HTML, dosłowne atrybuty — są na tym etapie scalane w pojedyncze fragmenty tekstu.
3 · Emisja
Drzewo jest wypisywane jako kod JavaScriptu i przekazywane do new Function albo zapisywane na dysk przez CLI, gdy chcesz je obejrzeć lub spakować.
Po cichu, w kilku miejscach
Verso nie jest popularnym projektem i nie próbuje być. Pobierają go około 40 000 razy w miesiącu, głównie te same potoki budowania, i to rozmiar, który możemy uczciwie utrzymywać.
Jeśli porównujesz go z czymś większym: wybierz Verso, gdy renderujesz HTML na serwerze, chcesz przeczytać cały silnik w jedno popołudnie i wolisz nie audytować drzewa zależności. Wybierz coś innego, jeśli potrzebujesz reaktywności po stronie klienta — Verso nie ma zdania o DOM i nigdy mieć nie będzie.