Svelte Kit的load函数调用Prisma Client的正确服务端实现方法
Svelte Kit 服务端调用 Prisma Client 正确方案
报错原因说明
你之前的写法触发报错是因为两个核心问题:
- 普通
+page.ts/+layout.ts中的load函数是同构函数,会同时在服务端和客户端执行,客户端执行时自然触发Prisma Client禁止在浏览器运行的报错 - 不带
.server后缀的普通_ts文件默认允许被客户端代码导入,一旦被前端引用就会把Prisma逻辑打包进前端包触发报错
核心原则
所有Prisma Client的调用逻辑必须放在Svelte Kit标记的服务端专属上下文中,Svelte Kit会保证这些代码永远不会被打包到客户端。
具体可行实现方式
1. 服务端专属Load函数(最常用)
把数据查询逻辑写在带.server后缀的load文件中:+page.server.ts(页面级服务端load)或者+layout.server.ts(布局级服务端load),这些文件里的代码仅在服务端执行。
示例代码(src/routes/posts/+page.server.ts):
import type { PageServerLoad } from './$types'; import prisma from '$lib/prisma'; // 提前初始化好的Prisma Client单例 export const load: PageServerLoad = async () => { // 所有Prisma调用都在服务端完成 const postList = await prisma.post.findMany({ where: { published: true }, take: 10 }); // 返回的数据会自动序列化传给前端页面 return { postList }; };
前端+page.svelte直接通过data prop接收返回值即可,不需要接触任何Prisma逻辑。
2. 服务端API路由
把Prisma调用写在API路由的+server.ts文件中,这类文件仅在服务端运行,前端可通过fetch调用接口获取数据。
示例代码(src/routes/api/posts/+server.ts):
import type { RequestHandler } from './$types'; import prisma from '$lib/prisma'; export const GET: RequestHandler = async () => { const postList = await prisma.post.findMany({ where: { published: true } }); return Response.json(postList); };
3. 服务端专属工具函数封装
如果有多处复用的Prisma查询逻辑,可以把逻辑封装在带.server.ts后缀的工具文件中,Svelte Kit会禁止这类文件被客户端代码导入,从根源避免泄露。
示例:新建src/lib/server/posts.server.ts封装查询逻辑:
import prisma from './prisma'; export async function getPublishedPosts() { return prisma.post.findMany({ where: { published: true } }); }
你可以在任意服务端上下文(服务端load、API路由)中导入调用这个函数,不用担心泄露到前端。
Prisma Client 初始化最佳实践
为了避免开发环境热重载重复创建Prisma Client实例,统一用以下方式初始化单例(src/lib/prisma.ts):
import { PrismaClient } from '@prisma/client'; const globalForPrisma = globalThis as unknown as { prisma: PrismaClient }; export const prisma = globalForPrisma.prisma || new PrismaClient(); if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
注意事项
- 不要在不带
.server后缀的普通ts文件、普通+page.ts/+layout.ts的load函数、+page.svelte/+layout.svelte组件中导入调用Prisma Client - 不要在客户端代码中直接导入任何包含Prisma调用逻辑的文件
内容的提问来源于stack exchange,提问作者Willem Vanhulle
相关产品推荐
相关产品推荐

