Server Actions 是什么?它和传统前端调用接口有什么区别?
简化版
Server Actions 是一些全栈框架提供的能力:前端组件可以声明一个在服务端执行的函数,用来处理表单提交、数据修改、重新校验缓存等逻辑。它和传统 fetch API 的区别是调用形式更贴近组件和表单,框架负责序列化参数、发请求、执行服务端函数并返回结果。但它不是魔法,本质仍是一次客户端到服务端的请求,仍然需要鉴权、校验、幂等、错误处理和安全边界。
详细版
传统模式里,前端提交表单会调用某个 REST 或 GraphQL 接口;Server Actions 则把这类服务端逻辑放到框架约定的函数中,开发体验更统一,尤其适合 SSR、RSC、表单和缓存再验证。
它的优势是减少样板代码、靠近页面逻辑、方便和框架缓存联动。风险是边界变模糊:开发者可能误以为函数只会被可信页面调用,从而忽略输入校验和权限控制。
面试时要同时讲开发效率和安全边界,这样答案才稳。
完整版教学
一、Server Actions 的基本思想
把某些数据修改逻辑声明为服务端函数。
页面或组件通过框架机制触发它。
框架把参数发送到服务端。
服务端执行函数,完成数据库写入、调用后端、清理缓存等操作。
执行结果再影响页面刷新或局部更新。
二、和传统 API 的对比
| 维度 | 传统 API 调用 | Server Actions |
|---|---|---|
| 调用方式 | 手写 fetch / axios | 框架约定触发 |
| 代码位置 | API 层和组件分离 | 更靠近页面逻辑 |
| 缓存联动 | 需要手动处理 | 通常有框架集成 |
| 复用边界 | 跨端复用更明确 | 更绑定框架 |
| 安全要求 | 必须校验 | 同样必须校验 |
三、适合场景
表单提交。
后台管理里的简单数据变更。
和页面强绑定的 mutation。
提交后需要重新验证 SSR 缓存的场景。
不太适合需要开放给多端、多系统复用的公共 API。
四、代码示例
// 伪代码:服务端执行的 action
export async function updateProfile(formData: FormData) {
"use server";
const user = await requireUser();
const name = String(formData.get("name") ?? "");
validateName(name);
await saveProfile(user.id, { name });
revalidatePath("/profile");
}
这段代码看起来像本地函数,但执行位置是服务端。
因此它能读取服务端 Cookie,也能访问服务端资源。
五、安全边界
Server Action 不能默认信任入参。
所有参数都来自请求,必须做类型校验和业务校验。
权限必须在 action 内部或下游服务校验。
敏感操作要考虑 CSRF、防重复提交、幂等和审计日志。
只要能被浏览器触发,就要按外部请求处理;写成函数不代表天然可信。
六、缓存和刷新
很多框架会把 Server Actions 和页面缓存再验证结合。
例如提交评论后,重新校验文章详情页或评论列表。
这能减少手写刷新逻辑。
但要避免过度刷新大范围缓存,导致 SSR 回源压力上升。
七、误区和追问
- 误区:Server Actions 可以替代所有 API。 对多端复用、开放平台、复杂接口契约来说,传统 API 仍然必要。
- 误区:函数在服务端就不需要校验。 攻击者仍可构造请求触发它。
- 误区:它一定比 fetch 性能更好。 它减少样板代码,不代表网络请求消失。
- 追问:Server Actions 能访问数据库吗? 技术上可以,但项目上常通过服务层封装,避免页面逻辑过度耦合数据层。
- 追问:怎么处理错误提示? 返回结构化错误或结合框架表单状态,不要只抛通用异常。
- 追问:适合团队大项目吗? 适合页面内聚逻辑,但要制定边界规范,否则会分散业务规则。
八、面试表达口径
可以说它提升了 SSR 全栈框架的开发效率,但必须保留服务端接口思维。
好的回答会把“开发体验”和“安全治理”同时讲出来。