Zod را برای اکوسیستم بردار؛ Valibot را وقتی باندل کلاینت بودجه دارد
انتخاب اعتبارسنج در Next.js اغلب مثل انتخاب باشگاه است. Zod آشناست، Valibot سبک است، و هر دو TypeScript را از اسکیما درمیآورند. تصمیم واقعی این است که اسکیما کجا اجرا میشود. اگر فقط پشت Server Action بماند، کیلوبایت کلاینت بحث اصلی نیست. اگر همان اسکیما با هر تعامل به مرورگر برود، اندازه باندل بخشی از محصول است.
در این مقایسه Zod v4 را معیار بگیر، نه خاطرهی v3. نسخه ۴ فاصله سرعت را نسبت به قبل کم کرده و Zod Mini را هم آورده، شکل تابعی و مناسب tree-shaking داخل همان خانواده. Valibot هنوز معمولاً در باندل خام برنده است چون اعتبارسنجها تابع جدا هستند و بستهبند فقط همانها را نگه میدارد. بنچمارک بدون مرز مشخص، فرم کلاینت در برابر فقط سرور، نویز است.
هر کتابخانه مالک چیست
Zod اسکیما را زنجیرهای مینویسی. `z.object`، رشته، ایمیل، و بعد `parse` یا `safeParse` روی مرز. نوع TypeScript از همان اسکیما درمیآید. اکوسیستم اطرافش عمیق است: React Hook Form، tRPC، سازنده اسکیما برای Drizzle یا Prisma، و ابزار OpenAPI. برای Server Action که اسکیما را به کلاینت نمیفرستد، Zod کامل هنوز پیشفرضی است که هم نفر جدید هم قدیمی میتواند در بازبینی بخواند.
Valibot ماژولار است. `v.object` و `v.pipe` و اعتبارسنجهای کوچک. سبک ایمپورت تابعیاش برای بعضی تیمها غریبه است و برای باندل درست است. هر دو استنتاج نوع، چک ناهمگام، resolver برای React Hook Form، و استفاده در Server Action را دارند. Standard Schema کمک میکند بعضی ابزارها هر دو را بپذیرند. پذیرفتن با «همه آموزشها پیشفرض همین است» یکی نیست. اگر کتابخانه کناری فقط مثال Zod دارد، جزیره Valibot یعنی ترجمه دائمی سند.
Zod Mini را دین سوم نکن. همان خانواده است برای جایی که اندازه را اندازه گرفتهای و نمیخواهی API را کاملاً عوض کنی. اگر بدون اندازه، «برای احتیاط» همهجا Mini کنی، فقط عادت تیم را دو پاره کردهای.
Zod وقتی گراف آداپتور محصول است
تیم از قبل با tRPC یا اسکیمای درج دیتابیس روی Zod کار میکند. مسیر آموزش داخلیتان `zodResolver` است. اسکیما عمدتاً روی Server Action و Route Handler زندگی میکند و قرار نیست داخل Client Component بزرگ تکرار شود. استخدام بعدی و نمونه رسمی ابزارها باید کمتعجب باشند. ویزارد چندصد فیلدی در کلاینت نداری که خود کد اعتبار بخش جدی جاوااسکریپت شود.
`safeParse` را روی مرز سرور بگذار. خطای فیلد را طوری برگردان که UI همان کلید را نشان دهد. اسکیمای کامل سرور را «برای راحتی» داخل Client Component ایمپورت نکن اگر گراف سنگینی را به باندل میکشد. یا یک اسکیمای کوچک انتقال بساز، یا روی سرور اعتبار کن و خطای ساختیافته برگردان.
هزینه صادقانه: اعتبار زنده و کامل در مرورگر با Zod هنوز باندل میسازد. قبل از استاندارد کردن Zod کامل برای فرم عمومی چندمرحلهای، اندازه را ببین. Zod Mini برای همان مورد است، نه برای اینکه نام تازهتری باشد.
Valibot وقتی کیلوبایت خودش محصول است
اعتبار داخل Client Component، مسیر Edge، یا Worker اجرا میشود و جاوااسکریپت فشرده یا شروع سرد بودجه دارد. تیم سبک ایمپورت تابعی را قبول میکند و همهچیز را از یک بشکه دوباره export نمیکند، چون آن کار tree-shaking را خراب میکند. فرم عمومی است و اعتبار لحظهای بخش محسوس مسیر اول است.
اینجا برد Valibot واقعی است، به شرطی که تنها اسکیمای پروژه نباشد که هیچکس جز نویسندهاش نمیتواند با سند بقیه ابزارها جفت کند. اگر نصف ریپو Zod است و یک فرم Valibot، مرز را بنویس. وگرنه نفر بعدی هر دو را به هم تبدیل میکند و هر دو را نصفه نگه میدارد.
قاعده کسبوکار سنگین، مثل یکتا بودن ایمیل، مال سرور است حتی اگر Valibot روی کلاینت سبک باشد. کلاینت برای بازخورد است. تکرار قانون روی سرور اجباری است، چه ابزار این طرف Valibot باشد چه Zod.
در App Router اسکیما را دو بار بیفکر نفرست
اشتراک کد بین فرم و Server Action وسوسهکننده است و گاهی درست است. فایل اسکیما اگر فقط نوع و قاعده کوچک باشد، ایمپورت از کلاینت ارزان است. اگر همان فایل به وابستگی سرور، کلاینت دیتابیس، یا اسکیمای غول بچسبد، مرز را شکستهای.
الگوی سالم: اسکیمای ورودی همان فرم، صریح و کوچک. اعتبار سرور با همان منبع یا با نسخهای که عمداً سختگیرانهتر است. خطای `safeParse` به شکل ثابت برای فیلدها. پیام کاربر فارسی و جدا از کد خطا. اینها به نام کتابخانه وابسته نیستند.
اگر بعداً دیدی باندل فرم عمومی بخش اعتبار را نشان میدهد، آن قطعه را به Valibot یا Zod Mini ببر، نه کل مونوریپو را. اگر دیدی هر کتابخانه جدید فقط Zod دارد و تیم کند شده، Valibot را به لبه کلاینت محدود کن و سرور را آشنا نگه دار.
پیام خطا را از کتابخانه جدا کن
شکل داخلی خطا در Zod و Valibot یکی نیست. اگر کامپوننت مستقیماً به `issues` یا مسیر اختصاصی یکی بچسبد، تعویض ابزار یا حتی اشتراک اسکیما با سرور گران میشود. یک تابع نازک خروجی را به نگاشت فیلد به پیام تبدیل کند. UI فقط همان نگاشت را بشناسد.
پیام پیشفرض انگلیسی کتابخانه را به کاربر فارسی نشان نده. یا پیام را در اسکیما خودت بنویس، یا کد خطا را به جمله محصول ترجمه کن. این کار کوچک است و کیفیت فرم را بیشتر از انتخاب بین دو کتابخانه عوض میکند.
پرسشهای کوتاه
یکی را برای همه ریپو قفل کنم؟ اگر مرز اجرا یکی است بله. اگر هم Worker سبک داری هم اسکیمای سرور چسبیده به ORM، دو انتخاب با مرز نوشته بهتر از یک انتخاب شعاری است.
Zod v3 را نگه دارم؟ اگر محصول پایدار است، مهاجرت را با دلیل انجام بده نه با اسم نسخه. دلیل معمولاً یا نیاز به رفتار v4 است یا اندازه. بازنویسی همزمان فرم، tRPC، و اسکیمای دیتابیس بدون تست مرز، ریسک الکی است.
اعتبار کلاینت را حذف کنم تا باندل صفر شود؟ برای فرم کوتاه گاهی تجربه بدتر از چند کیلوبایت است. حذف را جایی بکن که سرور سریع جواب میدهد و خطا را به فیلد برمیگردانی. وگرنه کاربر فقط دیرتر میفهمد.