Next.js 15 Server Actions 与表单处理实践概述Server Actions 在 Next.js 15 中提供了无刷新、类型安全且无需显式 API 路由的表单提交流。本文基于官方稳定能力验证 `"use server"`、`FormData`、`revalidatePath/revalidateTag` 与会话读写,给出可落地模板与安全注意事项。关键参数/概念`"use server"`: 将函数标记为 Server Action(仅服务端执行)。`FormData`: 直接在 Action 中接收并解析表单数据(无需手写 `bodyParser`)。失效与更新:`revalidatePath(path)`、`revalidateTag(tag)` 精确失效缓存与增量更新。会话与请求上下文:`cookies()`、`headers()` 在 Action 中可读写认证与请求头。数据获取缓存:配合 `fetch` 的 `cache/no-store` 与 `next.revalidate` 控制缓存一致性。实践/示例// app/actions/save-post.ts
"use server";
import { revalidatePath, revalidateTag, cookies } from "next/cache";
export async function savePost(formData: FormData) {
const title = String(formData.get("title") || "");
const content = String(formData.get("content") || "");
if (!title || !content) {
throw new Error("标题与内容为必填");
}
// 可选:会话读取(例如 CSRF/用户态校验)
const session = cookies().get("session")?.value || "anonymous";
// 写入数据库(伪代码,替换为实际 ORM/SDK)
await db.posts.insert({ title, content, author: session });
// 精确失效与刷新页面/列表
revalidatePath("/posts");
revalidateTag("posts:list");
return { ok: true };
}
// app/posts/new/page.tsx(Server Component)
import { savePost } from "@/app/actions/save-post";
export default function NewPostPage() {
return (
<form action={savePost} className="space-y-4">
<input name="title" placeholder="标题" required />
<textarea name="content" placeholder="内容" required />
<button type="submit">提交</button>
</form>
);
}
// 数据读取侧(配合 tag 进行增量更新)
export async function getPosts() {
const res = await fetch("https://api.example.com/posts", {
next: { tags: ["posts:list"], revalidate: 60 },
cache: "force-cache",
});
return res.json();
}
验证方法表单提交流:在开发与生产环境分别提交,通过页面刷新与数据列表变化验证 `revalidatePath/revalidateTag` 的生效。缓存一致性:切换 `cache/no-store` 与 `next.revalidate` 数值(如 60/300),观察接口命中率与页面数据一致性。会话上下文:设置/清除 `cookies()` 值进行权限校验与行为分支验证。注意事项Server Actions 仅在服务器执行,避免调用浏览器专属 API;与 Edge Runtime 搭配时使用 Web API(如 `crypto.subtle`)。安全治理:对 `FormData` 做严格校验与类型约束,防止注入与越权;必要时引入 CSRF 校验。版本兼容:示例基于 Next.js 15 验证,需确保 `app` 目录与 React 18+ 环境。

发表评论 取消回复