2025年5月23日

Prisma ORMがnode_modulesにコードを生成する理由と、それが変わる理由

Prisma ORMはこれまで、データベースクライアントをnode_modulesに生成してきました。この記事では、当初の決定の理由、それ以降に学んだこと、そして今後変更することについて説明します。

Why Prisma ORM Generates Code into Node Modules & Why It’ll Change

Prisma ORMがコード(Prisma Client)をnode_modulesに生成する理由

Prisma ORMは、最初のリリース以来、データベーススキーマに合わせたデータベースクライアント(「Prisma Client」と呼ばれる)を生成するために*コード生成*を使用しています。Prisma Clientライブラリは、Prismaスキーマに基づいて自動生成されるため、その構造を認識し、カスタムで型安全なクエリを提供できます。

コード生成はTypeScriptエコシステムにおいて最も一般的な方法ではなく、Prisma ORMはそれに依存した最初の人気ライブラリの1つでした。開発者にとっての親しみやすさを最大化するため、デフォルトでPrisma Clientをnode_modulesフォルダに生成することにしました。それは、開発者がアプリケーションにサードパーティライブラリを統合する際に慣れている方法だからです。

生成されたコードのカスタムロケーションは、当初からoutputフィールドを介して選択可能でしたが、このデフォルト設定により、Prisma ORMのさまざまなフレームワークや使用状況で統一された動作が実現されました。

デフォルトでPrisma Clientをnode_modulesに生成することは、最終的にほとんどの人にとって魔法のような「it just works™️」開発者体験をもたらしました…しかし、動かなかった場合を除いては!

v7でPrisma Clientの場所を変更する理由と方法

それ以来、開発者はnode_modules内の生成されたコードが原因で問題に遭遇しました。JS/TSエコシステムの多くのツールは、node_modulesディレクトリが(npmpnpmyarnなどの)パッケージマネージャーによってのみ変更されるという前提で動作します。

しかし、Prisma ORMでは、生成されたコードがデータベースの最新の状態を反映するように、データベーススキーマを変更するたびにPrisma Clientを再生成する必要があります。この要件と、生成されたコードをnode_modulesに入れるというデフォルトの選択が、エコシステム内の多くのツールの前提に反していました。

生成されたコードをnode_modulesに入れる場合の必要な回避策

多くのツールがnode_modulesはパッケージマネージャーによってのみ変更されるという前提で動作するため、私たち(およびコミュニティの他の人々)はスムーズな開発者体験を確保するために*回避策*を講じてきました。

例えば、TS言語サーバーがnode_modulesの変更を監視しないため、prisma generateを実行するたびにTS言語サーバーを再起動するようにPrisma VS Code拡張機能を調整しました。もう1つの例は、Prisma ORMがNext.jsを使用したモノレポで使用される際に、node_modulesからファイルが適切にコピーされることを唯一の目的とする@prisma/nextjs-monorepo-workaround-pluginパッケージです。

node_modulesに生成されたコードが存在するという核心的な問題に対する回避策は、専用パッケージからハードコードされたコードパスまで、さまざまな形で存在します。

今後何が変わるのか?

当初、Prisma Clientをnode_modulesに生成するという決定は、多くの開発者がPrisma ORMを使い始めるのに役立ち、スムーズで統一された開発者体験を提供しましたが、このような「魔法のような」動作が、開発者がPrisma ORMを使用する際に予期せぬ問題を引き起こすこともわかりました。

現在、魔法のような動作や不要な抽象化レイヤーを排除することで、Prisma ORMの使用における開発者体験をよりシンプルで予測可能なものにする作業を進めています。

この取り組みの一環として、常にoutputパスを必須とすることで、node_modulesにコードを生成するオプションを削除する予定です

この変更に先立ち、v6.6.0で非推奨の警告を追加し、ドキュメントを変更しました。これにより、コミュニティに不要な混乱が生じました。これについては、次のセクションで詳しく説明します。

この変更は今年後半にPrisma ORM v7の一部として導入され、新しいprisma-clientジェネレーターのみに影響します。このアプローチにはいくつかの利点があります

  • 生成されたコードは「通常の」アプリケーションコードとして扱われます。開発者はそれを完全に制御し、アプリケーションバンドルの一部としてどのように含めるかを決定できます。
  • 予測可能性が高まり、魔法のような動作による回避策が不要になります。
  • node_modulesはパッケージマネージャーによってのみ変更されるという前提との適合。

prisma-clientprisma-client-jsジェネレーター

私たちのリリースを追っている方ならご存知の通り、v6.6.0prisma-clientという新しいジェネレーターをリリースしました。

この新しいジェネレーターはESMをサポートし、さまざまなJSランタイムと互換性があり、全体的により柔軟で、カスタムのoutputパスを*必須*とします。

Prisma ORM v7では、これがPrisma ORMで使用されるデフォルトのジェネレーターとなり、現在のprisma-client-jsジェネレーター(魔法のようなnode_modules生成機能付き)はメンテナンスモードに移行されます。

v6.6.0以降のoutputパス設定に関する混乱

v7で予定されている変更に先立ち、必須となるoutputパスの破壊的変更に開発者が備えられるよう、node_modulesにPrisma Clientを生成することに頼らないように促したかったのです。

そこで、最近のv6.6.0リリースでは、prisma-client-jsジェネレーターでカスタムoutputパスを使用していない場合に、Prisma CLIの出力に以下の非推奨警告を導入しました

また、prisma init実行時に生成されるデフォルトのPrismaスキーマもoutputパスを含むように変更し、それに合わせてドキュメントを更新しました。

この働きかけが、予測不能で問題のある動作の排除と開発者へのより多くの制御提供により、良い効果しかもたらさないと期待していましたが、多くの人が実際に非推奨警告を見て、prisma-client-jsジェネレーターでカスタムoutputパスを使用するように切り替えた後、問題を報告しました。

ユーザーはsrc/generated/prismaでのlintingエラーを報告し始めました。特に、lintingエラーが検出されると操作を停止するNext.js開発サーバーなどで問題となりました。コードは生成されたものであるため、lintingエラーは実際には重要ではありませんが、ユーザーはデフォルトでsrc/generatedをlinting設定から除外していませんでした。

他のユーザーは、バンドラー、相対パス解決、その他多くの意図しない副作用に関する問題を報告しました。全体として、Prisma Clientをどこに生成し、どのようにバンドルするかについて、多くの混乱が見られました。

これらはすべて、Prisma Clientがnode_modulesにあったときは問題なく動作していたプロジェクトで発生しました。v7までこれらの問題を避けるため、CLI出力からの非推奨警告を再度削除し、コミュニティから提起された問題を修正する予定です。

今日、Prisma ORMでカスタムoutputパスを使用するべき時

これら全てが今日あなたにとって何を意味するかの要約(TLDR)です

  • 既存のPrisma ORMプロジェクトがあり、prisma-client-jsジェネレーターを使用している場合
    • 最近カスタムoutputパスを追加し、その変更が原因でエラーが発生した場合は、以前と同様にPrisma Clientをnode_modulesに生成するように戻すことができます。
    • Prisma ORMが今日、Prisma Clientをnode_modulesに生成して問題なく動作しているなら、何も変更する必要はありません。 Prisma ORM v7では、outputパスを指定してPrisma ORMを使用するデフォルトの方法として新しいprisma-clientジェネレーターが導入されます。その時期が来たら、アップグレードパスに関する包括的なドキュメントが提供されます。
  • 今日から新しいプロジェクトを始める場合は、バンドルの問題を回避し、Prisma ORM v7での今後の破壊的変更に備えるため、カスタムoutputパスを設定することをお勧めします。生成されたアセットは(ほとんどが)ソースコードであり、アプリケーションのバンドルに処理され含まれることを意図しているため、アプリケーションのソースツリー内(例: src/generated/prisma)のパスを使用することをお勧めします。
  • outputパスで問題が発生した場合(新しいprisma-clientジェネレーターを使用しているか、現在のprisma-client-jsジェネレーターを使用しているかにかかわらず)、新しいissueを開いていただければ、問題解決のお手伝いをいたします。

いつものように、ご意見やご質問がありましたら、Xでご連絡いただくかDiscordにご参加ください

次回の投稿をお見逃しなく!

Prismaニュースレターに登録する

© . All rights reserved.