主题
Next.js 原理与运行时
Server Actions 的序列化、安全和执行语义是什么?
Server Action 看起来像函数调用,实际是跨网络的服务端 mutation,必须按不可信 RPC 处理。
面试官想考什么
- 为什么 Server Action 不是普通函数? 考察编译和网络边界。
- 客户端传入对象能否直接写数据库? 考察输入校验和授权。
- 重复提交、CSRF 和幂等如何处理? 考察生产安全。
- mutation 后页面如何拿到新数据? 考察 revalidation 和客户端状态。
一句话回答
text
Server Action 是由框架暴露的服务端调用入口,参数要经过可序列化传输,因此必须像公开 RPC 一样做 schema 校验、session/权限复核、CSRF 防护和幂等;成功后再按资源失效策略更新缓存和 UI。面试回答详解
1. 执行链路
text
client form/call -> serialized request -> server action
-> auth -> validate -> domain mutation -> revalidate
-> structured result -> client UI"use server" 只是声明执行位置,不等于自动鉴权、自动校验或自动事务。
2. 参数和返回值
只传输支持的可序列化数据,文件、大对象、数据库连接、函数和类实例不应直接作为 action 参数。服务端使用运行时 schema 校验字段、长度、枚举和资源 id。返回值只包含 UI 需要的安全信息,内部异常不要原样暴露。
3. 安全边界
每个 action 都要读取当前 session,并验证租户、资源和动作权限。表单 token、cookie 和跨站请求要按部署方式做 CSRF 防护。隐藏按钮或在 Client Component 中禁用操作都不是安全控制。
4. 一致性和重复
提交需要 requestId/idempotency key。数据库写入和 outbox/revalidation 要考虑失败顺序。成功写入但 revalidation 失败时,应允许重试失效而不能再次产生副作用。
5. 适用边界
- 适合简单表单 mutation、近页面的领域操作。
- 不适合公开 API、第三方回调、长任务、文件上传和需要独立协议的流接口。
- 长任务应创建 job,前端查询或订阅状态。
可直接背诵的 30 秒回答
text
Server Action 虽然写成函数,实际是跨网络的服务端 RPC。所有参数都来自不可信客户端,要做序列化边界、运行时 schema、session、租户和资源权限校验,并处理 CSRF、幂等和错误脱敏。适合页面附近的短 mutation,文件、公开 API 和长任务应使用更明确的 Route Handler 或后台任务。扩展知识
Action 与 API 的选择
- Action:页面内部 mutation,表单体验好。
- Route Handler:明确 HTTP 契约、流、webhook 和外部调用。
- Domain service:复用业务规则,避免 Action 直接堆数据库细节。
面试官追问链
追问一:Server Action 自动防 CSRF 吗?
- 考察点:安全细节。
- 回答方向:不能用“框架提供入口”替代完整 CSRF 审查;根据 cookie/认证方式校验来源、token 和 SameSite 策略。
追问二:Action 返回数据库对象可以吗?
- 考察点:数据暴露。
- 回答方向:不建议。只返回最小 DTO,避免序列化内部字段、循环引用、敏感信息和不稳定对象。
追问三:revalidatePath 后客户端一定马上更新吗?
- 考察点:缓存层理解。
- 回答方向:不一定,Router Cache、CDN 和并发请求都可能影响可见时间;需要明确失效范围和客户端刷新策略。