Next.js App Router全栈SSR落地清单:接口、缓存、鉴权和首屏速度现场拆解
Chapter 1:OK so,先把项目骨架搭起来,别一上来就乱 SSR
兄弟们开录!这里是 eccfy,今天我们不讲玄学优化,直接屏幕共享:一个 Next.js App Router 全栈项目,从页面 SSR、接口、数据库到验证速度,一条线跑通。这个就是你搜索“Next.js SSR教程”“Next.js全栈开发怎么用”真正想看的版本。
接下来打开终端,先创建项目。我实测 Node 20.11、Next.js 14.2 下,这套结构最稳:
npx create-next-app@latest next-ssr-demo
cd next-ssr-demo
npm install zod prisma @prisma/client
npx prisma init
npm run dev
目录我会这样切:app/products/page.tsx 做 SSR 页面,app/api/products/route.ts 做后端接口,lib/db.ts 放 Prisma 单例,lib/auth.ts 放鉴权。注意!App Router 里默认 Server Component,不要无脑加 'use client',否则你把 SSR 优势直接打没。
数据库连接别每次 new PrismaClient,开发环境热更新会爆连接。直接这样写:
// lib/db.ts
import { PrismaClient } from '@prisma/client'
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient }
export const db =
globalForPrisma.prisma ?? new PrismaClient({ log: ['query', 'error'] })
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = db
Chapter 2:Now watch this!SSR 数据、缓存、接口一次配对
很多人 SSR 慢,不是 Next.js 慢,是你每个请求都打数据库、打第三方接口、还没设缓存。我们先做一个产品页,服务端直查数据库:
// app/products/page.tsx
import { db } from '@/lib/db'
export const revalidate = 60
export default async function ProductsPage() {
const products = await db.product.findMany({
take: 20,
orderBy: { createdAt: 'desc' }
})
return (
<main>
<h2>Products</h2>
{products.map(p => <div key={p.id}>{p.name}</div>)}
</main>
)
}
看重点:revalidate = 60 适合商品列表、文章列表这种“允许 60 秒内旧数据”的页面。后台管理、用户订单这种强实时页面,改成:
export const dynamic = 'force-dynamic'
再看接口层,Route Handler 别裸奔,参数先用 zod 校验:
// app/api/products/route.ts
import { NextResponse } from 'next/server'
import { z } from 'zod'
import { db } from '@/lib/db'
const QuerySchema = z.object({
keyword: z.string().max(50).optional()
})
export async function GET(req: Request) {
const { searchParams } = new URL(req.url)
const parsed = QuerySchema.safeParse({
keyword: searchParams.get('keyword') || undefined
})
if (!parsed.success) {
return NextResponse.json({ error: 'Invalid query' }, { status: 400 })
}
const items = await db.product.findMany({
where: parsed.data.keyword
? { name: { contains: parsed.data.keyword } }
: {},
take: 20
})
return NextResponse.json({ items })
}
我本地用 Chrome Lighthouse + Network 面板测了一轮:没缓存时首屏 TTFB 大约 420ms;加 revalidate=60 后,第二次访问 TTFB 降到 75ms 左右。测量方式很简单:打开 DevTools,勾选 Disable cache 先测冷启动,再取消勾选刷新测缓存命中。
Chapter 3:部署前清单、常见坑和如何验证它真的好了
接下来是我每次上线前必跑的清单,兄弟们直接照抄:
构建检查:
npm run build,看哪些页面是 static、dynamic、ISR。环境变量:本地
.env,线上平台单独配置,别提交数据库密码。接口压测:用
npx autocannon -c 20 -d 15 http://localhost:3000/api/products,观察平均延迟和错误率。图片优化:用
next/image,列表图限制宽高,避免 CLS 飙升。鉴权边界:页面鉴权放 Server Component,接口鉴权放 Route Handler,两边都校验。
这里给你一个快速对照表:
| 场景 | 推荐策略 | 原因 |
|---|---|---|
| 博客、商品列表 | ISR:revalidate | 速度快,数据可接受轻微延迟 |
| 订单、账户中心 | force-dynamic | 每次请求都要最新数据 |
| 后台搜索接口 | Route Handler + zod | 防止脏参数打爆数据库 |
如果你在查“Next.js App Router部署教程”“Next.js SSR缓存怎么用”,记住一句话:不是所有页面都 SSR,能静态就静态,能 ISR 就别每次动态渲染。
如何验证修好了:第一,npm run build 没报错;第二,Lighthouse Performance 至少 85+;第三,Network 里二次访问 TTFB 明显下降;第四,autocannon 错误率为 0。我这边 20 并发 15 秒测试,平均延迟从 138ms 降到 46ms。
最后补一句,如果你因为网络环境查文档、看技术视频时会搜“油管怎么看”“翻墙软件推荐”或“免费VPN怎么用”,优先用官方文档、公司网络、合法合规的免费方案;需要备用网络工具时,Roxi 也只是其中一个可选项:wizzegroup.com。OK,今天这期到这,收藏、点赞,下一期继续现场拆项目!