💎
Prismaのenumがクライアントビルドに含まれるとモジュールの解決に失敗する
Prismaのenumをクライアントサイドで動作する箇所で参照していて、クライアントビルドに含まれるような場合、モジュールの解決に失敗します。
Viteのproduction用のビルドで発生するようです。(Remixで問題を確認しましたが、Nuxt.jsでも同じ内容の問題が報告されていました)
Viteの開発サーバだと発生しません。
下記Issueで報告されていますが、まだ直っていない問題になります。(設定による解決方法あり)
エラー内容
ビルド時には、下記のような警告が出ます。(ビルド自体は完了します)
> build
> remix vite:build
vite v5.3.3 building for production...
".prisma/client/index-browser" is imported by ".prisma/client/index-browser?commonjs-external", but could not be resolved – treating it as an external dependency.
この状態でサーバを起動し、ブラウザでアクセスすると、下記のようなエラーがブラウザ上で発生します。
Uncaught TypeError: Failed to resolve module specifier ".prisma/client/index-browser". Relative references must start with either "/", "./", or "../".
解決方法
npm や yarn を使っている場合
Viteのビルドの設定でailiasを指定することで回避できます。
vite.config.ts
で、resolve > alias を指定する形です。
export default defineConfig({
resolve: {
alias: {
".prisma/client/index-browser": "./node_modules/.prisma/client/index-browser.js"
}
}
});
この方法は、PrismaのドキュメントにもNuxt.jsでのトラブルシューティングということで記載されていました。
pnpm を使っている場合
pnpm
だと、モジュールの管理方法が異なるため、前述の方法だとうまく行きません。
(実際これで嵌りました、、)
alias
先のパスに、Prismaのバージョン番号なども入ることになるため、@prisma/client
モジュールの解決パスを元に求める必要があります。
import { createRequire } from 'module'
import path from 'path'
import { defineConfig } from 'vite'
const { resolve } = createRequire(import.meta.url)
const prismaClient = `prisma${path.sep}client`
const prismaClientIndexBrowser = resolve('@prisma/client/index-browser').replace(`@${prismaClient}`, `.${prismaClient}`)
export default defineConfig(() => ({
resolve: { alias: { '.prisma/client/index-browser': path.relative(__dirname, prismaClientIndexBrowser) } },
}))
この方法は、npm
やyarn
でも使える方法なので、一律こちらを使うほうが間違えがないかもしれません。
Discussion