Prisma@7 は No Rust でも Rust Free でもない
Prisma のジェネレーション時のオプションについて
このあとの話のために、最初にジェネレーション時のオプションについて説明します。
-
provider = "prisma-client"
TypeScript で PrismaClient のコードを生成し、自分のコードの一部としてビルドに組み込む場合 -
provider = "prisma-client-js"
JavaScript で PrismaClient のコードを生成し、node_modules 経由で別パッケージとして利用する従来の機能
今回、Prisma@7 で売り出しているのはprovider = "prisma-client"です。
Prisma@7 で生成されたファイルを確認してみる
Rust Free と呼ばれる状態を作るため、以下の設定で PrismaClient の TypeScript 用コードを生成してみます。今回、対象の DB は PostgreSQL とします
- schema.prisma
generator client {
provider = "prisma-client"
engineType = "client"
output = "../app/generated/prisma"
}
ここで生成されたファイル中から、QueryCompiler がどのように呼ばれるのか該当コードを確認します
- prisma/internal/class.ts から、該当部分を抽出
async function decodeBase64AsWasm(
wasmBase64: string
): Promise<WebAssembly.Module> {
const { Buffer } = await import("node:buffer");
const wasmArray = Buffer.from(wasmBase64, "base64");
return new WebAssembly.Module(wasmArray);
}
config.compilerWasm = {
getRuntime: async () =>
await import("@prisma/client/runtime/query_compiler_bg.postgresql.mjs"),
getQueryCompilerWasmModule: async () => {
const { wasm } = await import(
"@prisma/client/runtime/query_compiler_bg.postgresql.wasm-base64.mjs"
);
return await decodeBase64AsWasm(wasm);
},
};
この部分が何なのかというと、base64 化された QueryCompiler の WASM を取り出して、バイナリにデコードした後、WebAssembly として投入しています。このquery_compiler_bg.postgresql.wasm-base64.mjsは 2,410KB あり、zip 圧縮をかけても 940KB ほどのサイズになります。Prisma を動作させるためには、この WASM が必須です。
QueryCompiler がどのように作られているかというと、以下が該当するコードです。
はい、Rust です。
Prisma の言っている Rust Free とは何か?
2025/4/30 の記事を見ると、辛うじて書いてあります
Prisma ORM's core engine has undergone a major shift from the Rust based query engine to a leaner TypeScript/WASM core (the Query Compiler).
Rust ベースのクエリエンジン(おそらくネイティブバイナリのこと)から、Query Compiler(TypeScript と WASM を組み合わせたもの)になったということらしいですが、その WASM は Rust 製です。
バンドルサイズが 90%小さくなったというのは、ネイティブバイナリを使用した場合の 14MB が、WASM 化で 1.6MB になったということです。QueryEngine から QueryCompiler の移行によって、WASM が不要になったわけではありません。
そして現在 Prisma は、Rust Free、No Rust という言葉を使い続け、混沌を呼び込んでいます。実際のところは、No native libraries です。
Prisma@7 は No Rust でも Rust Free でもない
Prisma@7 に対する公式 Blog は以下の内容になります。
もうバンドルサイズが何から 90% 減少したのかすら書いてません。さらにprovider = "prisma-client-js"をprovider = "prisma-client"にすれば rust-free になりそうな記述になってますが、後者は TypeScript のコードが生成されるというだけで、基本的な動作は変わりません。生成された TypeScript のコードは WASM を base64 の状態から読み込むのでバンドルサイズが増えます。現状、メリットがありません。
なぜ WASM を base64 にしているのか
モジュールバンドラ対策です。WASM ファイルを直接読み込むコードがあると、あらゆる環境に対応させる必要があります。WASM ファイルがどう扱われるかは、モジュールバンドラの設定次第であり、あらゆる環境に対する対応地獄が待っています。これを解決する簡単な方法は、JavaScript 内に WASM のバイナリを内包しておき、実行時に WebAssembly として放り込むことです。
Cloudflare のように WASM のモジュールファイルを直接読み込む必要のある環境では runtime の指定で、base64 から読み込むのを回避する必要があります。ちなみにruntime = "workerd"のような指定をした場合、以下のようなコードが生成されます。
config.compilerWasm = {
getRuntime: async () => await import("./query_compiler_bg.js"),
getQueryCompilerWasmModule: async () => {
const { default: module } = await import("./query_compiler_bg.wasm?module");
return module;
},
};
?moduleの部分は特定のモジュールバンドラに対する指示です。Cloudflare にはそのような指定方法は存在しません。つまりどういうことかというと、エラーを出して動きません。provider = "prisma-client"を指定して出力したコードは、直接自分で該当部分を削除しない限り動きません。
まとめ
Prisma もひどいが、巷の記事もひどい
誤解を招く公式 Blog の責任は大きいのですが、Rust Free、No Rust という部分を WASM を使わなくなったと誤解する記事が乱発されいます。
ちなみに Prisma を No Rust で使う方法として、Prisma Accelerate という Prisma 専用の有料サービスを使う方法があります。Prisma エンジン(Rust 部分)をリモート経由で外部実行する方式です。その機能を内包している Prisma Postgres というサービスがあります。このサービスは Prisma が No Rust をうたい始める前からあったのですが、そちらを利用して Prisma が No Rust になったんだという勘違い記事まで存在しています。そしてそれを参照して、さらに間違った記事が再生産されています。
あらゆる情報を疑う必要がある
私を含め、技術記事は間違いだらけです。有名な人の記事もけっこう間違ってます。そして公式の情報も正しいとは限りません。間違った記事を参照して、さらに間違った記事を再生産しているものも見受けられます。最低限自分で検証するまで、それが正しいということを前提としないでください。
Discussion