2023年6月時点の「DenoでPrisma Clientが動くかどうか」の情報まとめ

# 1秒まとめ

限定的ではあるが動く

# 動機

- Denoのnpm互換がリリースされてnode側の資産が利用できるようになってきた。
- 実際に使ってみると互換レイヤや対象パッケージの都合で使えないものも多い。
- WebAppを実装しようとしたときにDatabaseアクセス層としてPrismaが使えるかどうかが大きいと考えている。
- 現時点でDenoでPrisma(Prisma Client)を扱おうとしたときの筆者が知るつまづきポイントを纏めてみた

間違ってるよとかあれば優しくコメントで教えてほしい :pray:

# 公式にサポートしている動作方法

## Deno + Prisma Client(preview Deno) + Primsa Data Proxy

https://www.prisma.io/docs/guides/deployment/deployment-guides/deploying-to-deno-deploy

https://zenn.dev/laiso/articles/ec0d024b690146

- Deno(Prisma Client) -> Prisma Data Proxy -> Database で動作する
- Deno Deployでも動く

### 問題点

#### Data Proxy分のオーバーヘッドが常に掛かるようになる。

https://zenn.dev/aiji42/articles/ba7767e66fb439

https://qiita.com/tsutorm/items/cee97e218978de1d9e75

日本で使うとリージョンの問題で実際結構遅くなっちゃって不満

# 公式にサポートしていない動作方法

## Deno + Prisma Client(library)

https://github.com/prisma/prisma/issues/2452#issuecomment-1491748012

- Denoの `createRequire` で node互換の`require`を利用して、生成されたPrisma Client libraryをロードする方法

### 問題点

#### Deno Deployでは動かない

Prisma Client libraryはその先でRustで書かれた Prisma Engine を ネイティブ拡張としてロードしている。このバイナリファイル(*.so.node)をロードする機構は Deno DeployのようなV8 isolateなEdge runtimeでサポートされていないので使えない

#### 動作バージョンが限定的

prisma@4.12.0 以前まではこの方法でも動作したが、[prisma@4.13.0で行われた変更](https://github.com/prisma/prisma/pull/18426/files) によって ネイティブ拡張のロードが `require` から `process.dlopen` に変化した影響で利用できなくなってしまった。

```
error: Uncaught Error: Unable to require(`/app/prisma/generated/client/libquery_engine-debian-openssl-1.1.x.so.node`).
The Prisma engines do not seem to be compatible with your system. Please refer to the documentation about Prisma's system requirements: https://pris.ly/d/system-requirements

Details: process.dlopen is not a function
    at Yr.loadLibrary (file:///app/prisma/generated/client/runtime/library.js:106:777)
    at eventLoopTick (ext:core/01_core.js:182:11)
    at async rr.loadEngine (file:///app/prisma/generated/client/runtime/library.js:108:538)
    at async rr.instantiateLibrary (file:///app/prisma/generated/client/runtime/library.js:107:1838)
```

Denoにも `Deno.dlopen` というネイティブ拡張のロード機構は一応あるが、[第三引数の `flag` を渡す機構が存在しておらず](https://github.com/denoland/deno/issues/13508) また `process.dlopen` もまだNode互換として実装されていない。

# どうなっていくと良いと思うか

個人的には一番最後のWASM化が推し

## Prisma Data Proxyの適合リージョンがDeno Deployの展開リージョンをサポートする

現時点では以下の2リージョンにData Proxyが展開されています。

- US East 1 (West Virginia, United States)
- EU Central 1 (Frankfurt, Germany)

DatabaseがAsia/Tokyoな場所に有るようなケースにおいて、Proxyを経由する為に一旦欧米を経由しなければいけないことがボトルネックになる要因なので、東京か大阪リージョンで利用できるようになればこの問題は一定軽減できることが期待できます。

一応新リージョンのリクエストフォームがあるようなので、リクエスト上げていけば解決するかも。

## process.dlopenの互換実装をDeno側でサポートする

[Support for passing flags in Deno.dlopen](https://github.com/denoland/deno/issues/13508) が解決した上で、`process.dlopen` の互換実装がDenoから扱えるようになれば、prisma@4.13.0 移行でもDenoからPrisma Clientが利用できることが期待できます。

ただ、この解決策では引き続き Deno Deployでの利用はできません。

コンテナ化してCloudRunで動かしてるとかなら問題無いですが、Denoのエコシステムが使えないというのはあまり良い解決策では無いのかもしれない。

Denoチームに期待な解決策。

## Prisma Engineのネイティブ拡張をWASM化

https://zenn.dev/tekihei2317/scraps/d7d5c075b5195d

で詳しい。[Prototype WebAssembly Engine in Prisma CLI](https://github.com/prisma/prisma/issues/8626) で一部取り組みがすすんでいるが、Prisma EngineをWASMとして実行できるようになってくれれば Deno Deploy 含めエッジランタイムでも直接 DenoからPrisma Clientが扱えるようになる。

Prismaチームに期待な解決策。


# 参考リンク

- [PrismaのDenoサポートについて - uki00a](https://scrapbox.io/uki00a/Prisma%E3%81%AEDeno%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
- [ブラウザでPrismaを試せるプレイグラウンドを作りたかった - tekihei2317](https://zenn.dev/tekihei2317/scraps/d7d5c075b5195d)
- [prisma/prisma - Add support for Deno #2452](https://github.com/prisma/prisma/issues/2452)
- [prisma/prisma - Prototype WebAssembly Engine in Prisma CLI #8626](https://github.com/prisma/prisma/issues/8626)