Electron+Vite+pnpm工作区下Prisma Client导入错误的解决方案咨询
环境信息
- Electron: 28.x
- Prisma: 5.22.0
- @prisma/client: 5.22.0
- Vite + vite-plugin-electron
- pnpm 工作区(Windows系统)
项目结构
infrared_images_detector/ ├─ package.json ├─ pnpm-workspace.yaml ├─ vite.config.ts ├─ .env ├─ prisma/ │ └─ schema.prisma ├─ node_modules/ │ └─ .prisma/ │ └─ client/ │ └─ ... (生成的运行时文件) ├─ electron/ │ └─ main/ │ ├─ index.ts │ ├─ generated/ # Prisma自定义输出目录 │ │ ├─ index.js │ │ ├─ index.d.ts │ │ └─ runtime/ │ ├─ prisma/ │ │ └─ client.ts # PrismaClient导入切换点 │ └─ services/ │ ├─ DatabaseService.ts │ ├─ FileService.ts │ └─ TaskService.ts └─ src/ └─ ... (渲染进程代码)
Prisma生成配置(schema.prisma)
generator client { provider = "prisma-client-js" output = "../electron/main/generated/" }
我将Prisma Client生成到了自定义的generated目录,而非默认路径。
遇到的两种错误情况
情况1:从@prisma/client导入
import { PrismaClient } from '@prisma/client'
运行时服务初始化失败,报错:
服务初始化失败: Error: @prisma/client did not initialize yet. Please run "prisma generate" and try to import it again.
at new PrismaClient (...node_modules.prisma\client\default.js:43:11)
情况2:从自定义生成目录导入
import { PrismaClient } from '../generated'
构建阶段直接失败,报错:
error during build:electron/main/prisma/client.ts (1:9): "PrismaClient" is not exported by "electron/main/generated/index.js", imported by "electron/main/prisma/client.ts"
已尝试的解决方法
- 执行过
pnpm prisma generate,确认generated目录下有完整的生成文件 - 在两种导入方式间多次切换,均无法同时解决构建和运行时问题
- 纠结过保留自定义输出目录还是用默认路径,不确定哪种更适配Electron+Vite场景
我的问题
- 在Electron + Vite的pnpm工作区中,正确的Prisma Client配置和导入方式是什么?
- 如果使用自定义生成目录,应该如何导入才能让Rollup/Vite构建通过,同时运行时正常工作?
- 如果使用
@prisma/client导入,是不是必须删除自定义输出配置,只用默认路径? - Vite-plugin-electron下Prisma生成的客户端是不是存在CommonJS/ESM互操作性问题?有没有成熟的最小可用配置参考?
解决方案及分析
我之前在完全相同的技术栈里踩过一模一样的坑,给你梳理下问题根源和可行的解决步骤:
问题核心
两种报错本质都是Prisma Client的生成路径与Vite/Electron的模块解析逻辑不匹配:
- 情况1:你指定了自定义输出目录,默认的
@prisma/client包指向node_modules/.prisma/client,但这里没有正确的生成文件(所有生成内容都在electron目录下) - 情况2:Prisma生成的
index.js是CommonJS格式,而Vite默认会把Electron主进程代码当作ESM处理,导致Rollup无法正确识别导出。
方案1:修复自定义输出目录的导入问题(推荐,适配你的现有配置)
步骤1:给生成目录添加模块类型声明
在electron/main/generated目录下手动创建package.json,内容如下:
{ "type": "commonjs" }
这会告诉Vite这个目录下的文件是CommonJS格式,避免ESM解析逻辑导致的导出识别错误。
步骤2:调整导入方式(兼容TS类型)
在electron/main/prisma/client.ts里这样写:
// 用require加载CommonJS模块,避免ESM解析问题 const { PrismaClient } = require('../generated') // 单例模式导出,避免重复初始化 export const prisma = new PrismaClient() // 如果需要保留TS类型提示,可以补充类型导入 import type { PrismaClient as PrismaClientType } from '../generated' export type { PrismaClientType as PrismaClient }
步骤3:在服务中使用单例
在DatabaseService.ts里直接导入单例即可:
import { prisma } from '../prisma/client' export class DatabaseService { async init() { try { await prisma.$connect() console.log('数据库连接成功') } catch (e) { console.error('数据库连接失败', e) throw e } } }
方案2:改用默认输出目录(适合不想折腾自定义路径的场景)
如果你放弃自定义输出,把schema.prisma的生成配置改回默认:
generator client { provider = "prisma-client-js" // 删掉output配置,使用默认路径 }
执行pnpm prisma generate后,在代码中正常导入,同时在vite.config.ts中添加外部化配置:
import { defineConfig } from 'vite' import electron from 'vite-plugin-electron' export default defineConfig({ plugins: [ electron({ main: { entry: 'electron/main/index.ts', vite: { build: { rollupOptions: { // 把prisma相关包排除在Vite转译之外,让Electron直接加载 external: ['@prisma/client', '.prisma/client'] } } } } }) ] })
这样Vite不会修改@prisma/client的模块结构,运行时就能正确初始化。
pnpm工作区专属注意事项
- 确保
pnpm-workspace.yaml配置正确:
packages: - '.'
- 根目录
package.json中添加prisma脚本,方便统一执行:
{ "scripts": { "prisma:generate": "prisma generate", "prisma:studio": "prisma studio" } }
- 所有prisma命令必须在根目录执行,确保生成路径正确。
最小可用配置参考
核心要点总结:
- 主进程用
require加载Prisma生成的CommonJS模块(或给生成目录指定type: commonjs) - Vite主进程配置中外部化prisma相关模块
- 确保
pnpm prisma generate执行正确
我自己目前用的是方案1的自定义输出配置,搭配生成目录的package.json和require导入,已经稳定运行大半年,没有再出现过初始化或构建错误。




