Zod v4 がリリースされ、公式は「14倍高速」「バンドルサイズ57%削減」と発表しています。Hacker News で 782 ポイントを獲得するほど注目されていますが、実際のところどうなのでしょうか?
正直なところ、公式の数字をそのまま信じていいのか気になったので、自分で検証してみました。結論から言うと、公式発表は概ね正確でした。ただし、バンドルサイズにはバンドラー選択という落とし穴がありました。Zod でフロントエンド/バックエンドのバリデーションを一元管理している方も多いと思うので、この検証結果は参考になるはずです。
検証環境
まず、今回の検証環境を共有しておきます。
MacBook Pro M1 Pro
Node.js v22.21.1
zod v3.23.8
zod v4.0.0
mitata v1.0.34(高精度ベンチマーク)
esbuild v0.24.0 / Rolldown(バンドルサイズ計測)
パース速度のベンチマークには、公式と同じmitataライブラリを使用しました。mitata は V8 エンジンの JIT コンパイラ最適化を考慮した高精度ベンチマークツールで、ウォームアップや統計的な外れ値除去を自動で行います。Bun や Deno の公式ベンチマークでも採用されています。
パース速度の検証結果
実測値と公式発表の比較
公式と同じ mitata を使ってベンチマークを取った結果がこちらです。
| テスト | 実測値 | 公式発表 | 判定 |
|---|---|---|---|
| 文字列パース | 16x高速 | 14x高速 | 公式より良い |
| 配列パース | 3.8x高速 | 7x高速 | 差あり |
| オブジェクトパース | 6.0x高速 | 6.5x高速 | ほぼ一致 |
文字列パースは公式発表を上回る16倍という結果が出ました。オブジェクトパースも 6.0 倍で公式の 6.5 倍とほぼ一致しています。
開発環境に近い計測(tsx実行)
mitata は JIT 最適化を最大限に引き出す設計のため、本番環境に近い数値が出ます。一方、多くの開発者が日常的に使う tsx での計測結果も参考になります。
| テスト | tsx実行 | mitata | 差 |
|---|---|---|---|
| 文字列パース | 4.1x | 16x | JIT最適化の影響大 |
| 数値パース | 4.4x | - | - |
| 配列パース | 3.2x | 3.8x | ほぼ同等 |
| オブジェクト(単純) | 5.6x | 6.0x | ほぼ同等 |
| オブジェクト(複雑) | 1.7x | - | 複雑なスキーマは改善率低下 |
| Union型 | 3.5x | - | - |
| Optional/Nullable | 2.2x | - | - |
| Transform | 3.3x | - | - |
tsx 実行での平均は約3.5倍の高速化です。開発中に体感できる速度改善としては、この数字が現実的な目安になります。
計測方法による差の理由
mitata と tsx で差が出る理由は、JIT コンパイラの最適化です。
- mitata: 同じコードを繰り返し実行し、JIT が最大限に最適化された状態で計測
- tsx: TypeScript をトランスパイルしながら実行するため、JIT 最適化が十分に効かない
本番環境(ビルド済み JS)では mitata に近い数値が期待できます。開発中は tsx に近い体感になるでしょう。
パフォーマンス改善は本物
どちらの計測方法でも、v4 が確実に速くなっているのは事実です。公式発表は「最適化された条件での最大値」と理解しておけば、期待を裏切られることはありません。
TypeScript型チェックの改善
パース速度よりも体感しやすいのが、TypeScript の型チェック速度の改善です。
公式によると、同じコードをコンパイルした場合:
- v3: 25,000 以上の型インスタンス生成
- v4: 約 175 の型インスタンス生成
これは140倍以上の削減です。実際、複雑な Zod スキーマを持つプロジェクトでは、IDE のレスポンスが明らかに改善されます。
// このようなチェーンが多いプロジェクトで効果大
const schema = z.object({
user: z.object({
profile: z.object({
settings: z.object({
// 深いネストでも型推論が軽い
})
})
})
});
VSCode で「型推論が重い」と感じていた人は、v4 への移行でかなり改善するはずです。
バンドルサイズの落とし穴
ここからが重要な話です。公式は「バンドルサイズ57%削減」と発表していますが、これはバンドラーによって結果が大きく異なります。
バンドラー別の実測結果
| バンドラー | Zod v3 | Zod v4 | Zod v4 mini |
|---|---|---|---|
| esbuild | 13.5 KB | 60.5 KB | 54.9 KB |
| Rolldown | 13.2 KB | 14.9 KB | 3.8 KB |
※ すべて gzipped サイズ
esbuild では v4 が 4.5 倍大きくなりました。一方、Rolldown では v4 mini が 3.8 KBと、公式発表の 3.94 KB とほぼ一致しています。
なぜバンドラーで差が出るのか
v4 のアーキテクチャには「並列宣言」という仕組みがあります。例えばZodMiniStringが$ZodStringを継承する形で実装されており、esbuild では tree-shaking がうまく効きません。
これは GitHub の Issue #4637 で報告されている既知の問題で、CommonJS として使う場合は特に影響が大きく、AWS Lambdaのコールドスタートが24〜48%遅くなったという報告もあります。
解決策: Rolldownを使う
公式の数字を再現するには、Rolldown を使うのが最も確実です。
# Rolldownのインストール
npm install -D rolldown
Rolldown は Vite の次期バンドラーとして開発されており、tree-shaking の精度が高いのが特徴です。
esbuildを使い続ける場合
esbuild から移行できない場合は、以下の方法で影響を軽減できます。
Zod miniを使う
// これを
import { z } from 'zod';
// こう変える
import { z } from 'zod/mini';
esbuild でも mini を使うことで、フル版よりは若干小さくなります(60.5 KB → 54.9 KB)。
ESMを使う
CommonJS より ESM 形式の方が tree-shaking が効きやすいです。
// package.json
{
"type": "module"
}
v3から移行すべきか?
結論として、移行はおすすめです。ただし条件付きで。
移行をおすすめするケース
| 状況 | 理由 |
|---|---|
| パース速度を改善したい | 文字列16倍、オブジェクト6倍の高速化 |
| IDEが重い | 型チェック140倍改善 |
| Rolldown / Vite を使っている | miniで3.8KB、十分軽い |
| 新機能を使いたい | z.interface()、JSON Schema変換など |
慎重になるべきケース
| 状況 | 理由 |
|---|---|
| esbuild から移行できない | バンドルサイズが4.5倍に増加 |
| AWS Lambda(CommonJS) | コールドスタート悪化の可能性 |
| 安定性最優先 | v3は枯れている |
段階的移行が可能
Zod v4 はzod/v3パスで旧バージョンも提供しています。これを使えば、同じプロジェクト内で v3 と v4 を併存させながら段階的に移行できます。
// 既存コードはv3のまま
import { z } from 'zod/v3';
// 新しいコードはv4で書く
import { z as z4 } from 'zod';
検証コード
今回使用したベンチマークコードを公開しておきます。自分の環境でも試してみてください。
import { z as z3 } from 'zod3'; // npm:zod@3.23.8
import { z as z4 } from 'zod'; // zod@4.0.0
const ITERATIONS = 100_000;
const WARMUP = 1_000;
function bench(fn: () => void, iterations: number): number {
// ウォームアップ
for (let i = 0; i < WARMUP; i++) fn();
const start = performance.now();
for (let i = 0; i < iterations; i++) fn();
return performance.now() - start;
}
// 文字列パース
const stringSchema3 = z3.string();
const stringSchema4 = z4.string();
const v3Time = bench(() => stringSchema3.parse('hello'), ITERATIONS);
const v4Time = bench(() => stringSchema4.parse('hello'), ITERATIONS);
console.log(`v3: ${v3Time}ms, v4: ${v4Time}ms`);
console.log(`高速化率: ${(v3Time / v4Time).toFixed(1)}x`);
package.json の設定:
{
"type": "module",
"dependencies": {
"zod": "^4.0.0",
"zod3": "npm:zod@3.23.8"
}
}
まとめ
Zod v4 のパフォーマンス検証をまとめると:
| 公式発表 | 検証結果 |
|---|---|
| 文字列14倍高速 | 正確(16倍確認) |
| 配列7倍高速 | やや過大(3.8倍確認) |
| オブジェクト6.5倍高速 | 正確(6.0倍確認) |
| バンドル57%削減 | 条件付き(Rolldown必須) |
- パース速度: 公式発表は概ね正確。文字列 16 倍、オブジェクト 6 倍の高速化を確認
- 型チェック: 140倍以上の改善、IDE が重い人には特に効果的
- バンドルサイズ: バンドラー選択が重要。esbuild では 4.5 倍増加、Rolldown + mini なら 3.8 KB
- 移行判断: Rolldown / Vite ユーザーは移行推奨、esbuild / Lambda は慎重に
公式の数字は「Rolldown を使った場合」という前提があることを理解しておけば、v4 への移行は安心しておすすめできます。新規プロジェクトなら迷わず v4 を選んでください。