LoginSignup
3
2

More than 1 year has passed since last update.

Prisma を Google App Engine で使いたい場合

Last updated at Posted at 2021-07-18

TL; DR

普通にデプロイしてしまうとprisma generateをしていないせいでエラーが出る。解決策は以下の2つ。

案1. postinstallスクリプトに登録する

package.json
"scripts": {
  // 中略
  "postinstall": "prisma generate"
},
"dependencies": {
  "prisma": "<version>" // devDependenciesではなく、dependenciesに入れる
}

案2. prisma generate の出力先を変更する

schema.prisma
generator client {
  provider = "prisma-client-js"
  // ここを追加するだけ
  output   = "../src/generated/client"
}
// 生成先のパスを参照する
import { PrismaClient } from './generated/client'

概要

  • Node.jsでバックエンドを書いている
  • ORMにはPrismaを使っている
  • インフラは Google App Engine (以下、GAE)を使う

以上の条件のとき、問題が発生したので、その解決策を残す。

問題1 prisma generate しないとクライアントが使えない

prisma のクライアントを使うときは、事前にprisma generateを実行する必要がある。GAE ではインスタンス開始時に npm scripts のstartに設定したコマンドが実行されるので、startを以下のように変更した。

package.json
"scripts": {
  "start": "prisma generate && node dist",
}

問題2 GAEのファイルは read only

しかし、GAEのファイルは read only であるため、prisma generateが失敗してしまった。

Error: EROFS: read-only file system, unlink '/workspace/node_modules/.prisma/client/index.js'

解決策

案1

npm scripts のpostinstallに指定したコマンドはnpm installもしくはyarn installが実行された後に続けて実行される。ここにprisma generateを設定する。
ただし、GAEではデプロイ時にdependenciesのみがインストールされ、devDependenciesがインストールされないことに注意したい。primsaライブラリは基本的にdevDependenciesのほうにインストールするが、この解決策を取る場合は、dependenciesに移動する必要がある。

package.json
"scripts": {
  // 中略
  "postinstall": "prisma generate"
},
"dependencies": {
  "prisma": "<version>" // devDependenciesではなく、dependenciesに入れる
}

かんたんに設定できるが、prismaライブラリの分、node_modulesが肥大化する。スピンアップが遅くなり、コールドスタートが長くなる可能性がある。

※一応、本番環境でのみyarn remove prismaを走らせることで回避できそう。

scripts/prisma_init.sh
#!/bin/bash
yarn prisma generate
if [[ $NODE_ENV = 'production' ]]; then
  yarn remove prisma 
fi
package.json
 "postinstall": "bash scripts/prisma_init.sh"

案2

prisma generateの出力先はデフォルトだと、node_modules内だが、GAEはデプロイ時にインスタンス側でnpm installが走り、その後は read only になるため都合が悪い。つまり、出力先を node_modules外に変更できれば、解決する。
公式ドキュメントを読んだところ、↓を見つけた。
https://www.prisma.io/docs/concepts/components/prisma-client/working-with-prismaclient/generating-prisma-client#using-a-custom-output-path

以下のようにすれば解決した。

schema.prisma
generator client {
  provider = "prisma-client-js"
  // ここを追加
  output   = "../src/generated/client"
}

PrismaClientをインポートしているコードも書き換えた。

import { PrismaClient } from './generated/client'

この方法のメリットはprismaをdependenciesに入れなくてすむので、サイズが軽くなり、コールドスタートが軽減されること。(ただし、ベンチマークを測ったわけではない)
デメリットはprisma generateを実行した環境がWindowsやMacだと、そのOS用の prisma バイナリが生成され、これがGAE環境では実行できないこと。

最後に

GAE はインフラにかかる工数を大幅に削減できるメリットがあるが、自由度は低い。
ただ、その低い自由度の中でも解決策は案外見つかる。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2