バージョニング
更新 — 2025年7月8日
[email protected] が npm に公開されました。パッケージルート("zod")は現在、Zod 4 をエクスポートしています。他のすべてのサブパスは変更されておらず、永続的に利用可能です。
Zod 4 にアップグレードするには:
Zod 4 を使用している場合、既存のインポート("zod/v4" および "zod/v4-mini")は永続的に機能し続けます。ただし、アップグレード後、任意で インポートを次のように書き換えることができます:
| 以前 | 以後 | |
|---|---|---|
| Zod 4 | "zod/v4" | "zod" |
| Zod 4 Mini | "zod/v4-mini" | "zod/mini" |
| Zod 3 | "zod" | "zod/v3" |
ライブラリ作成者の方へ — ライブラリ作成者 ガイドに概説されているベストプラクティスに従って Zod 4 サポートをすでに実装している場合は、ピア依存関係(peer dependency)を更新して zod@^4.0.0 を含めてください:
その他のコード変更は必要ありません。 最新の 3.25.x リリースと 4.0.0 の間でコードの変更は行われませんでした。これにはメジャーバージョンのバンプは必要ありません。
サブパスバージョニングに関するいくつかのメモ
結局のところ、サブパスバージョニングスキームは、エコシステムに非破壊的な方法でアップグレードを強制するための必要悪でした。もし私が最初から [email protected] を公開していたら、ほとんどのライブラリは単純にピア依存関係をバンプし、エコシステム全体で「バージョンバンプ雪崩」を引き起こしていたでしょう。
現状では、Zod 4 に対する 広範なサポート がエコシステム全体に存在します。完全に痛みを伴わない移行プロセスはありませんが、私が恐れていた「バージョン雪崩」は起こらなかったようです。概して、ライブラリは Zod 3 と Zod 4 を同時にサポートすることができました:Hono、LangChain、React Hook Form など。数人のエコシステムメンテナが具体的に私に連絡をくれ、Zod 4 のサポートを段階的に追加することがいかに便利であったかを示してくれました(通常、これにはメジャーバージョンのバンプが必要です)。手短に言えば、このアプローチはうまくいきました!Zod と同じ制約を受けるライブラリは他にほとんどありませんが、大規模な関連エコシステムを持つ他のライブラリには、同様のアプローチを検討することを強くお勧めします。
Zod 4 におけるバージョニング
これは、ユーザーと Zod の関連ライブラリエコシステムが Zod 4 に移行しやすくすることを目的とした、Zod 4 のバージョニングへのアプローチに関する記事です。
一般的なアプローチ:
- Zod 4 は最初
[email protected]として npm に公開されません。代わりに、[email protected]と並んでサブパス("zod/v4")でエクスポートされます。 - それにもかかわらず、Zod 4 は安定しており、本番環境で使用できると見なされています。
- Zod 3 は、パッケージルート(
"zod")および新しいサブパス"zod/v3"から引き続きエクスポートされます。バグ修正と安定性の向上を引き続き受け取ります。
このアプローチは、Golang がメジャーバージョンの変更を処理する方法に似ています: https://go.dev/doc/modules/major-version
その後:
- パッケージルート(
"zod")は、Zod 3 のエクスポートから Zod 4 への切り替えを行います。 - この時点で
[email protected]が npm に公開されます。 "zod/v4"サブパスは永続的に利用可能です。
なぜですか?
Zod はエコシステム内で独特の位置を占めています。エコシステム内の多くのライブラリ/フレームワークは、ユーザー定義の Zod スキーマを受け入れます。これは、それらのユーザー向け API が Zod とそのさまざまなクラス/インターフェース/ユーティリティに強く結合していることを意味します。これらのライブラリ/フレームワークにとって、Zod への破壊的変更は必然的にユーザーに対する破壊的変更を引き起こします。Zod 3 の ZodType は Zod 4 の ZodType に代入できません。
なぜライブラリは単に v3 と v4 を同時にサポートできないのですか?
残念ながら、peerDependencies の制限(およびパッケージマネージャー間の不一致)により、1つのライブラリの2つのメジャーバージョンを同時にエレがントにサポートすることは非常に困難です。
もし私が単純に [email protected] を npm に公開した場合、Zod エコシステムの大多数のライブラリは、Zod 4 を適切にサポートするために新しいメジャーバージョンを公開する必要があります。これには AI SDK のような有名なライブラリも含まれます。これはエコシステム全体で「バージョンバンプ雪崩」を引き起こし、一般的に多大な不満と作業を生み出すでしょう。
サブパスバージョニングにより、この問題を解決します。これは、ライブラリが Zod 3 と Zod 4(Zod Mini を含む)を同時にサポートするための簡単な方法を提供します。ライブラリは "zod" に単一の peerDependency を定義し続けることができます。npm エイリアス、オプションのピア依存関係、"zod-compat" パッケージ、またはその他のそのようなハックのような不可解な解決策は必要ありません。
ライブラリは、"zod" ピア依存関係の最小バージョンを zod@^3.25.0 にバンプする必要があります。その後、実装で Zod 3 と Zod 4 の両方をお参照できます:
その後、v4 に対する広範なサポートが得られたら、npm でメジャーバージョンをバンプし、パッケージルートから Zod 4 のエクスポートを開始して、移行を完了します。(これはすでに発生しました — このページの上部にあるメモを参照してください。)
ライブラリが関連するサブパス(ルートではなく)から排他的にインポートしている限り、その実装はコードを変更することなくメジャーバージョンのバンプをまたいで機能し続けます。
(少なくとも Go を使用しない人々にとっては!)非正統的に見えるかもしれませんが、これは私が知る限り、Zod のユーザーとより広いエコシステムのライブラリの両方に対して、クリーンで段階的な移行パスを可能にする唯一のアプローチです。
なぜこの状況でピア依存関係(peer dependencies)が機能しないのかについての詳細な掘り下げ。
あなたが Zod スキーマを受け入れる関数 acceptSchema を構築しようとしているライブラリだと想像してください。Zod 3 または Zod 4 のスキーマを受け入れられるようにしたいとします。この仮説では、Zod 4 がサブパスなしで zod@4 として npm に公開されたと想像します。あなたの選択肢は次のとおりです:
-
npm エイリアスを使用して、zod@3 と zod@4 の両方を
dependenciesとして同時にインストールする。これは機能しますが、Zod 3 と Zod 4 の両方の独自のコピーを含めることになります。ユーザーの Zod スキーマが、依存関係から取得しているのと同じ z.ZodType クラスのインスタンスであるという保証はありません(instanceofチェックはおそらく失敗します)。 -
複数のメジャーバージョンにまたがるピア依存関係を使用する:
"zod@>=3.0.0"...しかし、ライブラリを開発するときは、開発対象のバージョンを選択する必要があります。通常、これを開発依存関係としてインストールします。あなたのコードが両方のバージョンで一字一句違わずに機能することを確実にする責任はあなたにあります。多くの非常に基本的なクラスでジェネリクスが簡略化/変更されているため、Zod 3 と Zod 4 の場合、これは不可能です。 -
オプションのピア依存関係。私は、すべてのプラットフォームで実行時にどのピア依存関係がインストールされているかを確実に判断する方法について、明確な答えを見つけることができませんでした。オンラインの多くの回答は、「try/catch 内で動的インポートを使用してパッケージが存在するかどうかを確認する」と言っています。これらの人々は、フロントエンドのバンドラーにはこのための余裕がないため、あなたがバックエンドにいると想定しています。インストールされていない依存関係をバンドルしようとすると失敗します。明らかに、ビルドステップ中に try/catch 内にいるかどうかは関係ありません。また:同じライブラリの複数のバージョンについて話しているため、
package.jsonで2つのバージョンを区別するには npm エイリアスを使用する必要があります。v10 ほど最近の npm バージョンでも、ピア依存関係 + npm エイリアスの組み合わせを処理できません。 -
zod-compat。オンラインで見られるこの非常に曖昧な解決策は、「いくつかの基本機能を表すインターフェースをバージョンごとに定義する」というものです。基本的には、ライブラリが本物を近似するために使用できるいくつかのユーティリティタイプです。これはエラーが発生しやすく、多くの作業が必要で、実際の実装と同期させる必要があり、最終的にライブラリはおそらく詳細を欠いたシャドウバージョンのライブラリに対して開発することになります。また、これは型に対してのみ機能します。ライブラリが Zod 内のランタイムコードに依存している場合、それは崩壊します。
したがって、サブパスです。

