Next.js SSR场景下页面导航加载过慢问题咨询
问题根因与修复方案
1. 最核心性能问题:每次请求重复创建Prisma客户端实例
你当前代码中getServerSideProps每次触发、GetTotalCount函数每次调用都会执行new PrismaClient(),这会导致每次请求都要新建数据库连接、初始化Prisma引擎,仅这一步就能吃掉几百到上千毫秒延迟,高并发下还会直接打满数据库连接数。
- 修复方式:全局复用单个PrismaClient实例,新建
lib/prisma.ts文件写入以下代码:
import { PrismaClient } from '@prisma/client' const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined } export const prisma = globalForPrisma.prisma ?? new PrismaClient() if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
后续所有用到Prisma的位置都从该文件导入实例,删掉GetTotalCount和getServerSideProps里的new PrismaClient(),以及finally块中的await prisma.$disconnect()——长驻复用的实例不需要每次请求后断开连接。
2. 渲染选型错误:列表页没必要走纯SSR
纯SSR每次请求都要在服务端跑完所有逻辑再返回HTML,本身首字节时间就会高于静态渲染,你的房产列表页数据不需要毫秒级实时更新,完全没必要用getServerSideProps。
- 修复方式:把
getServerSideProps换成getStaticProps+增量静态再生(ISR),配置revalidate: 60,即页面生成后60秒内的请求直接走CDN缓存,超过60秒后后台静默重新生成新页面,用户完全感知不到加载等待,导航速度可以和纯React客户端渲染持平。如果要支持筛选参数的动态路由,配合getStaticPaths配置需要预渲染的分类、交易类型路径即可,其余路径走fallback: 'blocking'策略。
3. 数据查询逻辑的不必要损耗
现有代码有两个可直接优化的查询点:
- 不需要查询完整images数组再手动截取第一个,Prisma支持直接取关联数组的指定元素,修改select配置即可,大幅减少数据库返回的数据量:
const select = { id: true, type: true, bathrooms: true, rooms: true, price: true, propertySize: true, images: { take: 1, // 仅查询第一张封面图 }, title: true, location: true, purpose: true, currency: true, description: true }
- 分页计算逻辑存在bug:
Math.round(totalCount / itemsPerPage)算出的总页数不准确,应该用Math.ceil(totalCount / itemsPerPage)向上取整,否则最后一页数据会被错误跳过。
4. 部署环境带来的额外延迟
你当前将站点部署在Netlify上,Next.js的SSR接口会运行在Netlify的无服务器函数环境中,如果数据库和Netlify函数节点不在同一个地理区域,仅数据库TCP握手、查询传输的网络延迟就能占到1-2秒。
- 优化建议:如果坚持使用纯SSR,将服务和数据库部署在同区域云厂商;如果换成前面提到的ISR方案,该问题会自动解决——所有页面都缓存到CDN节点,不需要每次请求回源跑函数、查数据库。
补充说明:Next.js本身性能完全可以支撑大型站点,绝大多数SSR慢的问题都是错误的实例化方式、不合理的渲染策略选型导致的,改完以上几个点,页面导航耗时基本可以压到300毫秒以内。
内容的提问来源于stack exchange,提问作者Vito Medlej
相关产品推荐
相关产品推荐

