用途
本技能是 Payload 3.x 的权威参考。Payload 3 是 Next.js 原生、TypeScript 优先的无头 CMS,安装进 Next.js(App Router)应用后,提供自动生成的管理面板、REST + GraphQL API、类型化 Local API、认证、访问控制、文件存储与实时预览,全部基于一套开源 TypeScript 代码库。
版本说明(依据 payloadcms.com/docs,2026-06 核实):Payload 3 是 Next.js 全栈框架,不再有独立的 Express 服务器。配置位于 src/payload.config.ts,Payload 通过已安装的 (payload) 路由组挂载进 Next App Router。不要沿用 Payload 2.x 的“独立 Express 应用”指导。
架构概览
- payload.config.ts:唯一事实来源,包含 collections、globals、db 适配器、插件、admin、auth。
- Collections:可重复的文档组(Posts、Users、Media),核心构建块。
- Globals:单例(单个文档),如站点设置、页头/页脚导航。
- Fields:组合文档结构,同时驱动管理 UI、校验与访问控制。
- Local API:类型化的进程内数据访问(payload.find(...)),无 HTTP,服务端运行。
- REST / GraphQL:基于同一批 collections 自动生成的 HTTP API。
- 数据库适配器:@payloadcms/db-postgres、db-mongodb 或 db-sqlite。
- 存储适配器:本地磁盘(开发)或 S3/R2 等用于上传。
在 Next.js 应用中的位置
src/ 下包含 payload.config.ts(配置)、collections/(每个 CollectionConfig 一个文件,如 Users.ts、Posts.ts、Media.ts)、globals/(GlobalConfig 文件)、app/((payload)/ 为 Payload 生成的管理与 API 路由组,(frontend)/ 为你的 Next.js 前端,使用 Local API)。
Collections 核心结构
CollectionConfig 包含 slug(必填、URL 安全标识符)、admin(useAsTitle、defaultColumns)、access(read/create/update/delete 授权)、versions(草稿/发布与修订历史)、hooks(生命周期)、fields(文档结构)。
Collection 属性用途:slug 为必填标识符(也是 REST/GraphQL 路由基础);fields 必填,定义文档结构、UI 与校验;access 按操作授权;hooks 生命周期入口(before/after change/read/delete);admin 管理面板 UI;auth 使集合成为认证集合;upload 使其成为上传集合;versions 提供草稿与修订历史。
Globals 与 Collections
“如果你的 Collection 只打算包含单个 Document,考虑改用 Global。”Globals(GlobalConfig)是单例,如站点设置、主导航,拥有相同的 fields/access/hooks/admin 接口,但只有一个文档。
Fields(80/20)
- text、textarea、number、email、date、checkbox:标量。
- richText:基于 Lexical 的富内容。
- select、radio:枚举。
- relationship:链接到其他集合(relationTo、hasMany)。
- upload:引用上传集合(媒体)。
- array:可重复的子字段组。
- blocks:灵活内容,每行从定义的块类型中选择。
- group:嵌套命名空间字段。
- row、collapsible、tabs:仅管理布局(除带 name 的 tabs 外不产生数据嵌套)。
- json、code:原始结构化/代码数据。
每个字段都可携带 access、hooks、validate、admin.condition(条件显示)以及 localized: true 用于 i18n。详见 references/hooks-and-fields.md。
访问控制——默认最小权限
访问函数返回布尔值或查询约束(行级过滤),对 Local API、REST、GraphQL 统一生效。例如 delete 返回 req.user?.role === 'admin';read 对非管理员返回 { author: { equals: req.user?.id } } 仅限本人。集合级(read/create/update/delete)与字段级(field.access.read/create/update)均存在,字段级用于隐藏/锁定单个字段。切勿在自定义端点绕过访问控制,应使用 req 上下文,不要手写跳过访问控制的数据库调用。Local API 可用 overrideAccess: true 供受信服务端代码使用,需刻意为之而非默认。完整模式(RBAC、多租户隔离、字段级)见 references/access-control.md。
Hooks——生命周期入口
hooks 包含 beforeChange(保存前修改数据)、afterChange(副作用:重新验证、通知)、beforeRead、afterRead(塑造输出文档)、beforeDelete、afterDelete(清理)。常见用法:在 afterChange 中调用 Next.js revalidatePath() / revalidateTag() 在发布时清除前端缓存。自 Next.js 16 起为 revalidateTag('posts', 'max'),第二个参数是 cacheLife 配置,单参数形式已弃用(Next 15 上单参数是唯一形式,传两个参数是 TypeScript 错误)。完整 hook 目录(collection、field、global、auth hooks)与版本表见 references/hooks-and-fields.md。
Local API(Next.js 超能力)
在服务端组件/路由处理器中进程内获取数据,无 HTTP 往返,完全类型化:通过 getPayload({ config }) 获取实例,再调用 payload.find({ collection: 'posts', where: { status: { equals: 'published' } }, depth: 1, limit: 10 })。payload.find / findByID / create / update / delete / findGlobal 与 REST 接口对应。除非 overrideAccess: true,访问控制仍然生效。
Next.js 中的缓存
为 Local API 读取打标签:Next 16 用 'use cache' + cacheTag,Next 15 用 unstable_cache(..., { tags }),然后在 afterChange hook 中通过 revalidateTag(tag, 'max') 失效。不要在 Payload hook 中使用 updateTag():它仅限 Server Actions,而 Payload 的 REST/GraphQL 写入运行在 Route Handler 中会抛错。depth 控制关系填充,保持较低以避免过度获取。
决策表
数据库适配器:Postgres(db-postgres)适用于关系型数据、SQL 报表、Vercel Postgres/Neon/Supabase,迁移重要时;MongoDB(db-mongodb)适用于文档型数据、灵活 schema、已有 Mongo 基础设施;SQLite(db-sqlite)适用于本地/边缘、小体积、简单部署。
存储适配器:本地磁盘仅开发用,不适用于无服务器(临时文件系统);S3 / R2(@payloadcms/storage-s3)用于生产,前置 CDN(CloudFront/Cloudflare),私有媒体用签名 URL,前端处理 403。
多租户:@payloadcms/plugin-multi-tenant 用于按 tenant 字段的标准租户隔离;自定义访问约束用于特殊隔离规则,通过行级 read/update 约束强制执行。
常见陷阱
- 用户看到不该看的数据:read 访问返回 true(无行过滤)。修复:从 read 返回查询约束,而非仅 true。
- Vercel 上本地磁盘上传消失:无服务器文件系统是临时的。修复:使用 S3/R2 存储适配器。
- 发布后前端陈旧:Next.js 缓存了读取。修复:在 afterChange hook 中 revalidateTag(tag, 'max') / revalidatePath。
- updateTag 在 hook 中抛错:它仅限 Server Actions,而 Payload 的 API 写入运行在 Route Handler。修复:使用 revalidateTag(tag, 'max'),或必须不提供陈旧内容时用 { expire: 0 }。
- S3 签名 URL 在前端 403:URL 过期。修复:优雅处理 403,刷新 URL。
- 关系获取过深:高 depth 填充一切。修复:保持 depth 最小,显式填充。
- 自定义端点泄露数据:绕过了访问控制。修复:通过 Local API 并开启访问控制,overrideAccess 仅保留给受信路径。
- 环境变量未校验:错误配置在运行时失败。修复:启动时用 zod 校验环境变量。
- 无实时协作:Payload 无内置 CRDT。修复:搭配 Liveblocks/Yjs,Payload 仍为最终状态的事实来源。
资产
assets/collection.config.template.ts:注释详尽的 Payload 3 CollectionConfig 起始模板(access + hooks + fields),标注了适配点。
另见
typescript-ops(配置类型、生成类型 payload generate:types)、react-ops(自定义管理组件、消费 Local API 的服务端组件)、api-design-ops(REST/GraphQL 接口设计、分页、版本控制)、auth-ops(认证集合、会话/JWT、访问控制背后的 RBAC/ABAC 模式)。
关键外部资源
What is Payload、Collections · Fields、Access control、Hooks、Local API、Database · Storage adapters、Multi-tenant plugin。