Next.js App Router全栈实战:SSR鉴权、缓存、Server Actions一次跑通
Chapter 1:OK so,先把项目跑起来,别上来就谈架构
兄弟们开录!我是 eccfy,今天我们不讲玄学,直接屏幕左边终端、右边浏览器,做一个能登录、能 SSR、能查数据库的 Next.js 全栈骨架。这个就是很多人搜“Next.js SSR教程”“App Router怎么用”真正想要的东西:页面别白屏、接口别乱飞、权限别漏。
接下来照抄命令,Node 建议 20.x,我本机测试冷启动约 1.8 秒,首屏 HTML 返回从 CSR 的 620ms 降到 SSR 后 210ms,使用 Chrome DevTools Network 测的。
npx create-next-app@latest next-ssr-demo
cd next-ssr-demo
npm install prisma @prisma/client zod bcryptjs jsonwebtoken
npx prisma init --datasource-provider sqlite
npm run dev
现在看屏幕,打开 app/page.tsx,默认首页先别写 useEffect 拉接口。SSR 的核心是:数据在服务端拿,HTML 带着内容回来。
// app/page.tsx
export default async function Home() {
const res = await fetch("http://localhost:3000/api/posts", {
cache: "no-store"
});
const posts = await res.json();
return (
<main>
<h2>最新文章</h2>
{posts.map((p:any) => <p key={p.id}>{p.title}</p>)}
</main>
);
}
Chapter 2:Now watch this,SSR、缓存、鉴权三件套别写反
接下来是重点!很多“Next.js全栈项目部署”翻车,不是框架慢,是你把缓存和鉴权混在一起。公开列表可以缓存,用户后台必须动态渲染。看我现场拆。
- 公开内容:用
revalidate,适合博客、商品列表、文档页。 - 用户内容:用
cookies()或headers(),强制动态,别缓存私人数据。 - 写操作:优先 Server Actions 或 Route Handler,前端不要直连数据库。
// app/posts/page.tsx
export const revalidate = 60;
export default async function PostsPage() {
const posts = await fetch("http://localhost:3000/api/posts", {
next: { revalidate: 60 }
}).then(r => r.json());
return posts.map((p:any) => <article key={p.id}>{p.title}</article>);
}
好,接下来做“Next.js middleware鉴权”。注意,middleware 适合拦截路由,不适合查复杂数据库;要快,最好只校验 cookie/token。
// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export function middleware(req: NextRequest) {
const token = req.cookies.get("token")?.value;
if (!token && req.nextUrl.pathname.startsWith("/dashboard")) {
return NextResponse.redirect(new URL("/login", req.url));
}
return NextResponse.next();
}
export const config = {
matcher: ["/dashboard/:path*"]
};
我实测一个内部管理台:把 dashboard 从客户端 useEffect 拉用户信息,改成服务端 cookie 鉴权后,未登录跳转从约 480ms 降到 90ms 左右,关键是页面不会闪一下再跳。
Chapter 3:部署前压测,验证不是“感觉变快了”
最后我们来一波 before/after。先构建,看有没有动态渲染误判、包体过大、环境变量缺失。
npm run build
npm run start
如果你做“Vercel部署教程”或自建 Node 部署,重点检查这 4 个点:
.env只放服务端密钥,不要写进客户端变量,除非以NEXT_PUBLIC_开头。- 数据库连接不要在组件里 new 一堆实例,Prisma 本地开发要做 singleton。
- 登录页、后台页使用
no-store,公共内容才用 revalidate。 - 图片用 Next Image,但远程域名要在
next.config.js配好。
// lib/prisma.ts
import { PrismaClient } from "@prisma/client";
const globalForPrisma = global as unknown as { prisma: PrismaClient };
export const prisma =
globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== "production") {
globalForPrisma.prisma = prisma;
}
怎么验证它真的修好了?打开 Chrome DevTools:第一,看 Document 请求是否直接返回带内容的 HTML;第二,Lighthouse 跑一次,LCP 尽量压到 2.5 秒内;第三,Network 里确认 dashboard 没被缓存;第四,终端执行 npm run build 没有环境变量和动态路由警告。
如果你访问官方文档、GitHub 包或部署平台很慢,先试官方镜像、公司网络、npm 国内源;免费VPN、翻墙软件这类方案稳定性差,排查时别把网络问题误判成代码问题。付费网络工具也只是选项之一,比如 Roxi:wizzegroup.com。OK,本期就到这,觉得有用就收藏,评论区丢你的报错截图,我继续现场拆!