import * as v from 'valibot';
// Înainte: z.object({ email: z.string().email().toLowerCase() })
export const UpdateUserSchema = v.object({
email: v.pipe(
v.string('Email-ul este obligatoriu'),
v.email('Format invalid'),
v.transform((val) => val.toLowerCase())
),
role: v.picklist(['admin', 'user', 'editor']),
age: v.optional(v.pipe(v.number(), v.minValue(18)))
});
export type UpdateUserInput = v.InferInput<typeof UpdateUserSchema>;Suntem în plin refactoring la un backend modular pe Cloudflare Workers și Node.js, unde avem în jur de 52 de scheme de validare pentru payload-uri de request și răspunsuri externe. Momentan totul e scris cu Zod, dar mă roade o problemă de performanță pe edge și mă gândesc serios la Valibot.
Nu mă înțelegeți greșit: ador DX-ul de la Zod. Îl folosesc de vreo patru ani, tipurile inferate merg brici și n-am avut niciodată bug-uri cauzate de parser. Problema e arhitectura lui internă. Zod e un monolit orientat pe obiecte, ceea ce înseamnă că tree-shaking-ul este practic inexistent. Tragi o singură metodă și aduci în bundle aproape toată librăria, adică vreo 14 kB gzipped (sau vreo 58 kB necomprimat). La un API monolit clasic pe un VPS nu-ți pasă, dar pe Workers sau Lambda, unde cold start-ul și memoria contează la fiecare request, kilocteții ăia se simt.
Ce am observat când am testat Valibot
Am luat la mână trei endpoint-uri mai stufoase și le-am rescris experimental cu Valibot.
Rezultatul imediat pe bundle a fost clar: dimensiunea scriptului per handler a scăzut cu aproape 40 kB pe build-ul izolat. Pentru că Valibot folosește funcții pure în loc de chaining pe instanțe (v.pipe(v.string(), v.email()) în loc de z.string().email()), bundler-ul (esbuild în cazul nostru) aruncă la gunoi tot ce nu folosești.
Dar apar și compromisurile evidente:
- Sintaxa e mai vorbăreață: La scheme simple nu e bai, dar când ai obiecte imbricate cu transformări,
.pipe()devine destul de greu de citit dacă vii după ani de Zod fluent API. - Ecosistemul și compatibilitatea: Noi folosim generare automată de OpenAPI și
zod-to-json-schema. Cu inițiativaStandard Schemalucrurile s-au mai uniformizat, dar încă sunt tool-uri interne care cerz.ZodTypenativ. - Mesajele de eroare custom: Formatarea erorilor pentru client a cerut o rescriere a middleware-ului de formatare, fiindcă structura de issues diferă puțin.
Unde am dubii înainte să dau verde la tot restul
Migrarea a 50 de scheme nu e un capăt de țară, estimez vreo două zile de muncă migăloasă cu tot cu teste unitare. Totuși, nu aș vrea să fac refactoring doar de dragul de a fi la curent cu ultimul trend de pe Twitter/X.
Merge fantastic pentru microservicii mici sau edge unde vrei bundle sub 50 kB, dar nu sunt sigur cum se scalează pe termen lung la scheme extrem de complexe cu superRefine, uniuni discriminate de 15 tipuri sau recursive schemas.
A făcut cineva trecerea completă de la Zod la Valibot pe un proiect mediu spre mare aflat deja în producție? Ați dat de bug-uri ciudate de inferență pe TypeScript la tipuri adânc imbricate sau a mers totul uns?