Valibotが最近Builder.io(Qwik)の紹介で話題に上がっているスキーマベースのバリデーションライブラリとなります。
We ♥️ Open Source.
— Builder.io (@builderio) July 25, 2023
Happy to feature @FabianHiller on our blog with this introduction to his new library, Valibot! https://t.co/WZl6rjJgWK
一番注目されているのはバンドルサイズの部分だと思います。Zodと比較すると、98%のバンドルサイズの削減ができると言われています。さらに、モジュール化されていて、非常にtree-shakingしやすく、確かにバンドルサイズが大幅に減少できるでしょう。
早速使ってみた感想をシェアしようと思います。
メリット:拡張しやすいアーキテクチャ
非常にわかりやすい構造になっており、ソースコードが読みやすいです。そして、モジュール化やピュア関数化が行われているため、非常にテストしやすくなっています。驚くべきことに、テストのカバレッジはなんと100%となっています。
構造がシンプルのため、非常に拡張しやすいです。例えば、日本の郵便番号をチェックするバリデータを簡単に作成できます。
import { ValiError } from 'valibot';
import type { ValidateInfo } from 'valibot';
// xxx-xxxx
const postCodeWithHyphenReg = /^\d{3}-\d{4}$/;
// xxxxxxx
const postCodeWithoutHyphenReg = /^\d{7}$/;
/**
* Creates a validation function that validates a post code in Japan.
* 100-9999 or 1009999
* @param hyphened
* @param error
* @returns
*/
export function postCode<TInput extends string>(
hyphened = false,
error?: string,
) {
return (input: TInput, info: ValidateInfo) => {
if (
(hyphened && !postCodeWithHyphenReg.test(input)) ||
(!hyphened && !postCodeWithoutHyphenReg.test(input))
) {
throw new ValiError([
{
validation: postCode.name,
origin: 'value',
message: error || 'Invalid post code',
input,
...info,
},
]);
}
return input;
};
}
デフォルトのものと同じように使えます。
const personalInfoSchema = object({
firstName: string(),
lastName: string(),
postCode: string([postCode()]),
});
もちろん、Zodのrefine
を使えば、バリデーションのカスタマイズもできますが、Valibotほどテストしやすくないでしょう。
import { z } from 'zod';
export const zPostCode = (hyphened = false) =>
z
.string()
.refine(
(value) =>
(hyphened && postCodeWithHyphenReg.test(value)) ||
(!hyphened && postCodeWithoutHyphenReg.test(value)),
{
message: 'Invalid post code',
},
);
Valibotを基礎として、信頼性の高い拡張ライブラリを簡単に作成できることは、Valibotの最大の魅力の1つだと思います。さらに、拡張ライブラリを使用してもtree-shakingが効果的に行われるため、バンドルサイズが増えることがありません。本当に素晴らしい特徴ですね。
デメリット:多言語対応
これはValibotの問題より、モジュール化(ピュア関数化)の特性として考えられるかもしれません。Valibotを見た瞬間、これが好きだと思いました。このライブラリはdate-fns
を思い起こさせます。Moment.js
の代替としてのdate-fns
は同じピュア関数の塊で、もう1つの代替であるdayjs
と競合していると思われます。dayjsがtree-shakingに向いていない一方、言語の切り替えが容易です。一方、date-fnsがtree-shakingに向いているが、言語の設定が難しいです。
同じように、Zod
がsetErrorMap
を通して、デフォルトのエラーメッセージを簡単に上書きできる一方、Valibotが各バリデータに直接エラーメッセージを渡さなければいけないのです。
Valibotにもグローバルのメッセージを導入できる可能性はありますが、この部分のtree-shakingは難しいと感じることがあるかもしれません。実際に、ピュア関数がグローバルな要素を参照するのは少し奇妙に感じます。通常、ピュア関数は引数に依存し、外部の状態を変更しないように設計されますが、グローバルなメッセージを参照する場合はこの原則が崩れる可能性があります。そのため、この点を考慮して設計を検討することが重要です。適切な設計することで、tree-shakingを有効に活用しつつ、グローバルなメッセージを導入する方法を見つけることができるかもしれません。
完了
Zodと比べると、Valibotが一長一短です。英語圏ではかなり有力な代替候補者となりますが、多言語対応ができるまで、日本語圏では厳しいかもしれません。極端なパフォーマンスを求められるウェブアプリが少ないからなのです。Valibotの成長を見守っていきましょう。
興味があれば試してみたらいかがでしょうか。では。