Valibot vs Zod: Ukuran Bundle dan Tree-Shaking

Foto oleh Nikowsk via Wikimedia Commons (CC BY-SA 4.0)
Ya, dan dengan selisih besar untuk skema tipikal. Valibot v1 hanya sekitar 1,3 kB gzipped karena setiap skema dan validasi adalah fungsi terpisah yang bisa tree-shaking. Zod v4 klasik sekitar 13 kB karena API method chaining-nya membundel semuanya ke satu objek, dan bahkan ekspor zod/v4-mini yang lebih baru sekitar 3,9 kB.
API klasik Zod merangkai method dari satu objek, sehingga setiap validator berada pada class yang sama. Sebuah bundler tidak dapat membuktikan Anda tidak pernah memanggil method tertentu hanya karena tidak muncul di kode Anda, jadi ia menyimpan seluruh runtime. Valibot menghindari ini dengan menjadikan setiap validasi sebuah fungsi terekspor mandiri.
Tidak. Menulis pernyataan import-star-as-v terlihat seperti mengimpor semuanya, tetapi bundler modern seperti esbuild, Rollup, dan Rolldown menganalisis named export mana yang benar-benar Anda referensikan dan membuang sisanya. Impor namespace murni kemudahan ergonomis tanpa penalti ukuran bundle.
Biasanya tidak, kecuali ukuran bundle adalah batasan keras yang terukur seperti batas ukuran edge-function. Biaya refactor, hilangnya adapter khusus Zod, dan risiko perbedaan validasi yang halus jarang sepadan di server, tempat ukuran bundle tidak relevan. Ukur dulu, baru putuskan.
zod/v4-mini adalah ekspor yang bisa tree-shaking yang diperkenalkan di Zod v4 yang menggantikan method chaining dengan fungsi check mandiri, menurunkan biaya gzipped menjadi sekitar 3,9 kB. Gunakan ketika Anda ingin tetap di ekosistem Zod tetapi butuh bundle lebih kecil untuk browser atau edge. Ini lebih verbose daripada Zod klasik tetapi tetap lebih besar daripada Valibot.

Foto oleh Nikowsk via Wikimedia Commons (CC BY-SA 4.0)
Ringkasan Utama
Untuk frontend yang sensitif terhadap ukuran bundle dan edge function, Valibot mengalahkan Zod dari sisi ukuran: Valibot v1 hanya sekitar 1,3 kB gzipped karena fungsi skema dan validasinya adalah modul terpisah yang tree-shakeable. Zod v4 standar membundel semuanya sekitar 13 kB; ekspor baru zod/v4-mini menurunkannya menjadi sekitar 3,9 kB, tetapi desain pipe modular Valibot tetap unggul.
Saya menggunakan Zod di hampir setiap proyek TypeScript yang saya kerjakan. Itu menjadi default karena alasan yang jelas: API-nya nyaman, inferensi tipenya sangat baik, dan ekosistem di sekitarnya sangat besar. Tetapi pada proyek terbaru saya mengirim validasi ke sebuah Cloudflare Worker dan mengawasi anggaran bundle dengan ketat, dan berat Zod menjadi masalah nyata. Saat itulah saya mulai serius mempertimbangkan Valibot, dan perbedaannya tidak kecil.
Pertanyaan intinya bukan library mana yang memvalidasi lebih baik. Keduanya benar, keduanya menginferensi tipe dengan rapi, keduanya mencakup bentuk data yang sama. Pertanyaannya adalah apa yang berakhir di bundle produksi Anda, dan itu bergantung pada satu keputusan arsitektural yang dibuat masing-masing library tentang cara Anda menyusun sebuah skema.
API klasik Zod adalah method chaining pada satu objek. Anda mengimpor satu hal dan memanggil method darinya. API yang ergonomis itulah yang membuatnya sulit diperkecil. Ketika Anda menulis impor di bawah ini, bundler menarik seluruh graf class karena setiap method berada pada objek yang sama; sebuah bundler tidak dapat membuktikan bahwa Anda tidak pernah memanggil parser tanggal string atau discriminated union hanya karena Anda tidak mengetiknya di sini.
// Zod classic — one import, everything comes with it
import { z } from "zod";
const LoginSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
type LoginData = z.infer<typeof LoginSchema>;
// The whole Zod runtime (~13 kB gzipped) is now in your bundle,
// even though this schema uses maybe five features.Ini bukan cacat melainkan sebuah trade-off. Method chaining terbaca dengan indah dan itulah alasan begitu banyak dari kita jatuh cinta pada Zod. Tetapi objek yang membawa semua method itu adalah satu unit yang tidak terpisahkan menurut bundler.
Valibot membalik desainnya. Alih-alih method pada sebuah class, setiap skema dan setiap validasi adalah fungsi mandiri yang Anda impor berdasarkan nama. Batasan disusun dengan fungsi pipe yang mengalirkan sebuah nilai melalui rangkaian aksi. Karena setiap aksi adalah fungsi terekspor tersendiri, bundler hanya menyimpan fungsi yang benar-benar Anda referensikan dan membuang sisanya. Ini adalah tree-shaking buku teks, dan itulah sebabnya Valibot v1 hanya sekitar 1,3 kB gzipped untuk skema tipikal.
// Valibot — import only the functions you name
import * as v from "valibot";
const LoginSchema = v.object({
email: v.pipe(v.string(), v.email()),
password: v.pipe(v.string(), v.minLength(8)),
});
type LoginData = v.InferOutput<typeof LoginSchema>;
// Parse the same way you would with Zod
const result = v.parse(LoginSchema, { email: "[email protected]", password: "secret12" });Impor wildcard (import star as v) terlihat seperti menarik semuanya, padahal tidak. Bundler modern seperti esbuild, Rollup, dan Rolldown menyelesaikan named export mana yang benar-benar Anda gunakan dan menyingkirkan sisanya. Impor namespace hanyalah kemudahan ergonomis, bukan biaya ukuran bundle.
Maintainer Zod jelas mendengar keluhan soal ukuran bundle. Zod v4, yang dirilis awal 2025, memperkenalkan ekspor terpisah zod/v4-mini yang meninggalkan method chaining demi fungsi check mandiri, jauh lebih dekat dengan gaya Valibot. Ini menurunkan biaya gzipped menjadi sekitar 3,9 kB, peningkatan besar dari build standar sekitar 13 kB. Tangkapannya adalah API-nya jauh lebih verbose daripada Zod klasik, dan Anda melepaskan sebagian ergonomi chaining yang membuat Zod menyenangkan sejak awal.
// zod/v4-mini — standalone checks, no method chaining
import * as z from "zod/mini";
const LoginSchema = z.object({
email: z.string().check(z.email()),
password: z.string().check(z.minLength(8)),
});
type LoginData = z.infer<typeof LoginSchema>;
// ~3.9 kB gzipped — smaller than classic Zod,
// still roughly 3x heavier than Valibot for the same schema.| Dimensi | Valibot v1 | Zod v4 (klasik / mini) |
|---|---|---|
| Ukuran gzipped (skema tipikal) | ~1,3 kB | ~13 kB klasik / ~3,9 kB mini |
| Model komposisi | Fungsi mandiri + pipe() | Method chaining / .check() di mini |
| Bisa tree-shaking | Ya, sejak desain | Tidak (klasik) / Ya (mini) |
| Ergonomi API | Eksplisit, lebih banyak impor | Sangat fluent (klasik) / verbose (mini) |
| Ekosistem & adapter | Berkembang, bagus tetapi lebih kecil | Sangat besar, standar de facto |
| Paling cocok | Edge, browser, kritis ukuran | Server Node, kode Zod yang ada |
Jangan memigrasikan basis kode Zod yang besar ke Valibot hanya untuk menghemat kilobyte di server. Biaya refactor, hilangnya adapter khusus Zod, dan risiko perbedaan validasi yang halus hampir tidak pernah sepadan kecuali ukuran bundle adalah batasan keras yang terukur. Ukur dulu, baru putuskan.
Ringkasan jujurnya: Valibot memenangkan argumen ukuran bundle begitu meyakinkan sampai Zod merestrukturisasi API-nya sendiri untuk menjawabnya. Itu dukungan terkuat yang bisa didapat Valibot. Tetapi Zod tidak diam saja, dan untuk sebagian besar pekerjaan server ergonomi dan ekosistemnya tetap menjadi default saya. Pilihlah berdasarkan di mana kode berjalan, bukan berdasarkan library mana yang lebih tren kuartal ini.