はじめに
Vue.jsのフルスタックフレームワークであるNuxtで、Node.js用のORMであるPrisma ORMを使って、アプリを作成していました。
npm run dev
で立ち上がる開発環境を使って開発し、本番環境へデプロイしようとnpm run build
を実行したところ、エラーが発生してビルドできませんでした。
最終的にビルドに成功することはなかったものの進捗はあったので、同じような状況になった方の参考になるかもしれないと思い、知見を共有します。
自分の環境
Windows
node : v18.18.0
npm : 10.9.0
package.json
より
関係なさそうなパッケージは除いています。
パッケージ名 | バージョン | 備考 |
---|---|---|
nuxt | ^3.16.2 | |
vue | ^3.5.13 | |
vue-router | ^4.5.1 | |
@prisma/nuxt | ^0.3.0 | 最終的にアンインストールした |
@prisma/client | ^6.7.0 | 後から追加した |
prisma | ^6.7.0 | 後から追加した |
@prisma/nuxt
を使用しての試行錯誤 -> 断念
(@prisma/nuxt
のインストール)
@prisma/nuxt
は、NuxtでPrismaを使う際に推奨される、設定の簡素化などをしてくれるモジュールらしいです。
上記サイトの通り、
npx nuxi@latest module add @prisma/nuxt
で@prisma/nuxt
を追加します。
エラー1 : Nuxt Build Error
npm run build
を実行したところ、次のようなエラーが発生しました。
> npm run build
ERROR ✗ Build failed in 2.13s 00:00:00
[nuxi 00:00:00] ERROR Nuxt Build Error: [commonjs--resolver] Invalid module ".prisma/client/index-browser" is not a valid package name imported from C:\ProjectRoot\node_modules\
file: C:/ProjectRoot/node_modules/@prisma/client/index-browser.js
解決策1 -> 進んだ?
調べると、Viteのaliasによって解決できるかもしれないという情報がありました。
上記サイトに倣い、nuxt.config.ts
に次の内容を追記しました。
vite: {
+ resolve: {
+ alias: {
+ ".prisma/client/index-browser": "./node_modules/.prisma/client/index-browser.js",
+ },
+ },
},
エラー2 : TypeError & Invalid module
再びnpm run build
を実行すると先程のエラーは消え、解決かと思いきや、今度は次のようないくつかのエラーが発生しました。
> npm run build
[nitro 00:00:00] ERROR TypeError [ERR_INVALID_MODULE_SPECIFIER]: Invalid module ".prisma" is not a valid package name imported from C:\ProjectRoot\node_modules\@prisma\client\default.js
[00:00:00] ERROR Invalid module ".prisma" is not a valid package name imported from C:\ProjectRoot\node_modules\@prisma\client\default.js
[00:00:00] ERROR Invalid module ".prisma" is not a valid package name imported from C:\ProjectRoot\node_modules\@prisma\client\default.js
解決策2 -> 失敗
Viteのaliasを、下記のようにさらに追加してみましたが、解決しませんでした。
vite: {
resolve: {
alias: {
".prisma/client/index-browser": "./node_modules/.prisma/client/index-browser.js",
+ ".prisma": "./node_modules/@prisma/client/default.js",
},
},
},
解決策2.5 -> 失敗
また、他の記事を参考に次のようにも書き換えてみましたが、解決しませんでした。
generator client {
- provider = "prisma-client-js"
+ provider = "prisma-client"
output = "../generated/prisma"
}
- import { PrismaClient } from '@prisma/client'
+ import { PrismaClient } from "~/generated/prisma/client";
npx prisma generate
断念
@prisma/nuxt
を使用しては、ビルドできないという判断に至りました。
@prisma/nuxt
をアンインストールして、ここまでの変更を戻しました。
ここまでの変更を戻す
- modules: ["@prisma/nuxt"],
+ modules: [],
vite: {
- resolve: {
- alias: {
- ".prisma/client/index-browser": "./node_modules/.prisma/client/index-browser.js",
- ".prisma": "./node_modules/@prisma/client/default.js",
- },
- },
},
generator client {
- provider = "prisma-client"
+ provider = "prisma-client-js"
output = "../generated/prisma"
}
- import { PrismaClient } from "~/generated/prisma/client";
+ import { PrismaClient } from '@prisma/client'
npm uninstall @prisma/nuxt
prisma
@prisma/client
へ切り替えて試行錯誤 -> 一瞬だけ成功 -> 失敗
prisma
@prisma/client
のインストール
Nuxt用のパッケージ@prisma/nuxt
ではなく、prisma
@prisma/client
を使えば解決できるかもしれないと思い、次のようにインストールしました。
npm install @prisma/client@latest prisma@latest
"scripts": {
- "build": "nuxt build",
+ "build": "prisma generate && nuxt build",
"dev": "nuxt dev --host",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
エラー1 : TypeError & Invalid module
npm run build
を実行すると、さっきも出たエラーが再発しました。
> npm run build
[nitro 00:00:00] ERROR TypeError [ERR_INVALID_MODULE_SPECIFIER]: Invalid module ".prisma" is not a valid package name imported from C:\ProjectRoot\node_modules\@prisma\client\default.js
[00:00:00] ERROR Invalid module ".prisma" is not a valid package name imported from C:\ProjectRoot\node_modules\@prisma\client\default.js
[00:00:00] ERROR Invalid module ".prisma" is not a valid package name imported from C:\ProjectRoot\node_modules\@prisma\client\default.js
解決策1 -> 前進
そこで、再び下記の記事を参考に次のようにも書き換えてみました。
generator client {
- provider = "prisma-client-js"
+ provider = "prisma-client"
output = "../generated/prisma"
}
- import { PrismaClient } from '@prisma/client'
+ import { PrismaClient } from "~/generated/prisma/client";
すると今度はビルドに成功しました。
> npm run build
✔ Nuxt Nitro server built
✔ You can preview this build using node .output/server/index.mjs
エラー2 : SyntaxError
ビルドに成功し、一件落着かと思いきや、node .output/server/index.mjs
で本番環境を立ち上げたところ、再びエラーが発生しました。
本番環境は立ち上がるのですが、サーバーサイドでPrismaを使う処理を走らせたときに、次のようなエラーが出て処理ができませんでした。
> node .output/server/index.mjs
Listening on http://[::]:3000
[request error] [unhandled] [POST] http://[::1]:3000/api/your-endpoint
SyntaxError: Identifier 'process' has already been declared
at ESMLoader.moduleStrategy (node:internal/modules/esm/translators:119:18)
at ESMLoader.moduleProvider (node:internal/modules/esm/loader:468:14) {
cause: SyntaxError: Identifier 'process' has already been declared
at ESMLoader.moduleStrategy (node:internal/modules/esm/translators:119:18)
at ESMLoader.moduleProvider (node:internal/modules/esm/loader:468:14),
statusCode: 500,
fatal: false,
unhandled: true,
statusMessage: undefined,
data: undefined
}
解決策2 -> 前進
何を参考にしたかがわからなくなったのですが、次のように変更したところ、SyntaxError
は解決しました。
- import { PrismaClient } from "~/generated/prisma/client";
+ import { PrismaClient } from "~/generated/prisma";
エラー3 : ReferenceError
今度は別のエラーが発生しました。
> node .output/server/index.mjs
Listening on http://[::]:3000
[request error] [unhandled] [POST] http://[::1]:3000/api/your-endpoint
ReferenceError: __dirname is not defined in ES module scope
at file:///C:/ProjectRoot/.output/server/chunks/_/prisma.mjs:831:16
at ModuleJob.run (node:internal/modules/esm/module_job:194:25) {
cause: ReferenceError: __dirname is not defined in ES module scope
at file:///C:/ProjectRoot/.output/server/chunks/_/prisma.mjs:831:16
at ModuleJob.run (node:internal/modules/esm/module_job:194:25),
statusCode: 500,
fatal: false,
unhandled: true,
statusMessage: undefined,
data: undefined
}
解決策3 -> 解決
エラーをよく見てみると、__dirname
が存在しないみたいです。
下記サイトなどを参考に、エラーの該当ファイル.output/server/chunks/_/prisma.mjs
に、追記をすることで解決しました。
830行目あたりにエラー要因のコードがあったので、その近辺に追記しました。
var M = k(require$$3); k(wi()); N("prisma:engines");
+ import { fileURLToPath } from 'url'
+ // import path from 'path' //pathはimport済みだったので不要でしたが、環境によってはここで定義する必要があるかもしれません
+ const __filename = fileURLToPath(import.meta.url)
+ const __dirname = path.dirname(__filename)
function fs() {
return M.default.join(__dirname, "../");
}
M.default.join(__dirname, "../query-engine-darwin");
これで、無事に動くようになりました!
> node .output/server/index.mjs
Listening on http://[::]:3000
解決策3.5 -> 失敗
解決策3の方法では、ビルド毎にファイルの書き換えが必要なため、あまり望ましくありません。
そこで、よりよい方法はないかと色々と模索してみましたが、どれもうまくいきませんでした。
generator client {
provider = "prisma-client"
output = "../generated/prisma"
+ runtime = "nodejs"
+ moduleFormat = "esm"
+ generatedFileExtension = "ts"
+ importFileExtension = "ts"
}
エラー4 : SyntaxError
不要なファイルを消すためにパッケージの再インストールなどをしていたら、先程のエラー2が再発するようになりました。
Gitを使ってコード管理をしているので、不用意に必要なファイルを削除してしまったということもなさそうなのです。
> node .output/server/index.mjs
Listening on http://[::]:3000
[request error] [unhandled] [POST] http://[::1]:3000/api/your-endpoint
SyntaxError: Identifier 'process' has already been declared
at ESMLoader.moduleStrategy (node:internal/modules/esm/translators:119:18)
at ESMLoader.moduleProvider (node:internal/modules/esm/loader:468:14) {
cause: SyntaxError: Identifier 'process' has already been declared
at ESMLoader.moduleStrategy (node:internal/modules/esm/translators:119:18)
at ESMLoader.moduleProvider (node:internal/modules/esm/loader:468:14),
statusCode: 500,
fatal: false,
unhandled: true,
statusMessage: undefined,
data: undefined
}
解決策4 -> 失敗
解決策2の方法はすでに試していますが、それでも治りませんでした。
色々と調べて、エラーを吐いているであろうファイルを直接書き換えたりも試してみましたが、うまくいかず、結局未解決となりました。
おまけ
エラー : crypto
バックエンドでcryptoというパッケージを使っていて、
開発環境ではcrypto.randomUUID()
というように使えていたのですが、本番環境ではそこがエラーを吐きました。
> node .output/server/index.mjs
Listening on http://[::]:3000
ReferenceError: crypto is not defined
at Object.handler (file:///C:/ProjectRoot/.output/server/chunks/routes/api/register.post.mjs:76:16)
at async Object.handler (file:///C:/ProjectRoot/.output/server/chunks/_/nitro.mjs:1967:19)
at async Server.toNodeHandle (file:///C:/ProjectRoot/.output/server/chunks/_/nitro.mjs:2238:7) {
cause: ReferenceError: crypto is not defined
at Object.handler (file:///C:/ProjectRoot/server/chunks/routes/api/register.post.mjs:76:16)
at async Object.handler (file:///C:/ProjectRoot/.output/server/chunks/_/nitro.mjs:1967:19)
at async Server.toNodeHandle (file:///C:/ProjectRoot/.output/server/chunks/_/nitro.mjs:2238:7),
statusCode: 500,
fatal: false,
unhandled: true,
statusMessage: undefined,
data: undefined
}
解決策
ちゃんとimportしてあげれば、問題なく動きました。
+ import { randomUUID } from "crypto";
- const uuid = crypto.randomUUID()
+ const uuid = randomUUID()
終わりに
なぜか、一度は正しく動いたのですが、最終的には解決できませんでした。
今回作っていたプロジェクトでは、Prisma ORMを使うのを諦め、Drizzle ORMへ移行しました。
参考文献はところどころに貼ってますが、実際にはPerplexityなども併用しています。