拓冰建站拓冰建站
首页 / 资讯中心 / 正文

使用 @payloadcms/payload-cloud 插件:为 Payload Cloud 接入 S3 文件存储、Resend 邮件与上传缓存

使用 payloadcms/payload-cloud 插件为 Payload Cloud 接入 S3 文件存储、Resend 邮件与上传缓存【免费下载链接】payloadPayload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.项目地址: https://gitcode.com/GitHub_Trending/pa/payload本指南以开源仓库中packages/payload-cloud/README.md为核心系统讲解 Payload 官方云插件payloadcms/payload-cloud的能力与接入方式。该插件将你的 Payload 实例与 Payload Cloud 托管的资源打通媒体文件写入由 Cloudflare CDN 加速的 S3 存储、邮件通过 Resend SMTP 交付、上传响应自动带缓存头并支持变更时主动清理缓存。读完你将掌握插件安装配置、可选参数、本地联调所需的环境变量以及其底层通过 collection hooks、upload handlers 与任务调度jobs协作的实现机制。一、插件是什么payloadcms/payload-cloud是 Payload 的官方云插件源码位于 packages/payload-cloud包名payloadcms/payload-cloud它的定位是把 本机/自建 Payload 升级为 跑在 Payload Cloud 上 时的资源连接层。README 明确了它提供的三项核心能力文件存储File storagePayload Cloud 提供由 Cloudflare 作为 CDN 的 S3 文件存储插件扩展 Payload 的 upload 集合使所有媒体文件保存在 S3 中而非本地磁盘。邮件投递Email delivery开箱即用的邮件投递服务由 Resend 驱动。上传缓存Upload caching默认对所有 upload 集合提供缓存同样经由 Cloudflare CDN 加速并处理缓存失效。除这三项外从源码src/plugin.ts可以看到插件还会向配置注入一个隐藏的 globalpayload-cloud-instance并接管config.jobs.autoRun用于保证定时任务只在多实例部署中的单个实例上运行。README 中 Future enhancements 提到后续还会增加API CDN——动态缓存 API 请求、并在资源更新时自动 purge。需要注意的前提这是一个云托管配套插件只有在 Payload Cloud 注入的环境变量齐全时才会真正生效详见下文执行开关本地普通 Payload 项目即使引入该插件也不会被改变行为。二、快速接入安装与最小配置2.1 安装在 Payload 项目中安装README 以 yarn 为例仓库本身使用 pnpm workspace 管理pnpm add同理yarn add payloadcms/payload-cloud该包以payload为 peerDependency且依赖aws-sdk/*、amazon-cognito-identity-js、nodemailer与payloadcms/email-nodemailer见package.json安装时会一并引入。2.2 在 Payload config 中启用import { payloadCloudPlugin } from payloadcms/payload-cloud import { buildConfig } from payload export default buildConfig({ plugins: [payloadCloudPlugin()], // rest of config })入口src/index.ts暴露了三个导出payloadCloudPlugin插件主入口、createKey构造 S3 对象键、getStorageClient获取已认证的 S3 客户端后两者一般只被插件内部调用也可供二次开发复用。2.3 执行开关什么时候插件真正生效README 明确指出This plugin will only execute if the required environment variables set by Payload Cloud are in place. If they are not, the plugin will not execute and your Payload instance will behave as normal.源码src/plugin.ts第一道关卡就是if (process.env.PAYLOAD_CLOUD ! true) { return config // 原样返回什么都不改 }也就是说只有在PAYLOAD_CLOUDtrue的环境中文件存储、邮件、上传缓存、jobs 接管才会被注入在本地普通开发环境未设该变量中插件是一个空转的 no-op[plugin.spec.ts](https://link.gitcode.com/i/1392a3acde632d3ab978dca8a07c9a04)中的 should return unmodified config测试用例正是对这一行为的验证。这一点对排查为什么插件好像没生效非常有帮助。2.4 关于自定义邮件 transport 的优先级README 有一则重要 NOTE如果 Payload config 里已经配置了带 transport 的 email它优先于 Payload Cloud 的邮件服务。源码src/email.ts中对应逻辑是当检测到args.config.email已存在时打印一条提示日志并直接返回已有 email 配置而不会用 Resend 覆盖它同时测试用例 should not modify existing email transport 也锁定了这一行为。如果你确认要使用 Payload Cloud 邮件应在插件选项中显式传email: false并自行清理 config 中的 email 设置。三、文件存储从本地磁盘到 S3启用存储后插件遍历所有带upload配置的 collection做三件事源码见src/plugin.ts的 storage 分支关闭本地落盘upload.disableLocalStorage: true追加 S3 上传/删除 hookbeforeChange上传、afterDelete删除追加静态文件 handler把文件 URL 的请求代理到 S3 读取原 collection 自定义 handler 会被保留在前面全局开启临时文件config.upload.useTempFiles: true配合大文件场景使用。3.1 上传beforeChange hookbeforeChangesrc/hooks/beforeChange.ts在写入数据库前把文件并发推送到 S3通过getIncomingFiles收集主文件及所有 Payload 生成的尺寸变体data.sizesreq.payloadUploadSizes因此原图与缩略图会全部上传文件对象键由createKey生成形如${identityID}/${PAYLOAD_CLOUD_ENVIRONMENT}/${collectionSlug}/${filename}即身份ID / 环境 / 集合名 / 文件名的结构天然做到不同项目、不同环境之间的对象隔离使用aws-sdk/lib-storage的Upload做分片并行上传源码注释说明默认 queueSize4、partSize5MB即最多缓冲约 20MB并注册httpUploadProgress事件输出 debug 日志便于观察大文件进度。3.2 删除afterDelete hookafterDeletesrc/hooks/afterDelete.ts在文档删除后遍历doc.filename以及doc.sizes中所有变体的文件名逐一deleteObject。注意这里的sizes数据来自文档快照hook 参数doc与上传侧的变体文件一一对应。3.3 读回static handler 与缓存头上传集合的访问 URL 请求最终落到src/staticHandler.ts的 handler用同一个createKey拼出键getObject从 S3 取回对象体与元数据响应头携带Content-Type、Content-Length、ETag并在缓存启用时附加Cache-Control: public, max-agemaxAgemaxAge 默认 86400 秒见下节对image/svgxml额外注入Content-Security-Policy: script-src none防止 SVG 内嵌可执行脚本这是值得注意的安全细节错误处理覆盖NoSuchKey与AccessDenied源码注释说明AWS SDK 找不到键时会尝试底层s3:ListBucket而桶策略禁止该操作因此 AccessDenied 往往意味着对象不存在二者均返回 404其余错误返回 500。开启debug选项时日志会携带完整错误对象便于排障。3.4 本地文件存储的认证与访问插件通过 AWS Cognito 换取临时凭证访问 S3。getStorageClientsrc/utilities/getStorageClient.ts会缓存 S3 client 与 Cognito session仅当 session 失效!session.isValid()时才调用refreshSession重新认证先用用户名/密码在 Cognito User Pool 登录拿到 ID Token再以该 token 作为身份池logins换取临时凭证最后以PAYLOAD_CLOUD_BUCKET_REGION构造 S3 client。因此在本地想直接读写云端文件资源时下面这组环境变量必须齐全README 原样给出也是代码中实际读取的变量名PAYLOAD_CLOUDtrue PAYLOAD_CLOUD_ENVIRONMENTprod PAYLOAD_CLOUD_COGNITO_USER_POOL_CLIENT_ID PAYLOAD_CLOUD_COGNITO_USER_POOL_ID PAYLOAD_CLOUD_COGNITO_IDENTITY_POOL_ID PAYLOAD_CLOUD_PROJECT_ID PAYLOAD_CLOUD_BUCKET PAYLOAD_CLOUD_BUCKET_REGION PAYLOAD_CLOUD_COGNITO_PASSWORD其中PAYLOAD_CLOUD_PROJECT_ID、PAYLOAD_CLOUD_COGNITO_PASSWORD、PAYLOAD_CLOUD_COGNITO_IDENTITY_POOL_ID是强校验项——缺失时getStorageClient会直接throw见src/utilities/getStorageClient.ts底部从而中止上传/删除/读取操作。补充说明这些值由 Payload Cloud 平台分配本地开发时属于联调配置不在本仓库内生成上述表格用于说明插件读取哪些变量及其用途。四、邮件投递Resend 开箱即用4.1 工作原理当满足PAYLOAD_CLOUDtrue、且环境变量PAYLOAD_CLOUD_EMAIL_API_KEY与PAYLOAD_CLOUD_DEFAULT_DOMAIN均存在时插件会调用payloadCloudEmail构建payloadcms/email-nodemailer适配器transport 指向 Resendnodemailer.createTransport({ auth: { pass: apiKey, user: resend }, host: smtp.resend.com, port: 465, secure: true, })默认发件人可被插件选项覆盖见第六节为defaultFromName缺省值Payload CMSdefaultFromAddress缺省值存在自定义域时取cms第一个自定义域否则取cmsdefaultDomain。apiKey或defaultDomain缺失时函数会直接抛错而 email 分支在 plugin 层额外加了条件判断只有两者齐全才会真正注入 Resend 适配器这与[plugin.spec.ts](https://link.gitcode.com/i/1392a3acde632d3ab978dca8a07c9a04) 的 should allow PAYLOAD_CLOUD_EMAIL_* env vars to be unset测试一致。4.2 From Domain必须是你有权限的域名README 强调邮件from地址必须来自你有权限的域名。Payload Cloud 会自动将你部署用的域名对应process.env.PAYLOAD_CLOUD_DEFAULT_DOMAIN加入白名单如果你配置了自定义域名这些域名同样会被加入白名单。尝试从一个你无权使用的域名发送邮件将不会成功。自定义域名如何被识别源码src/email.ts会扫描所有以PAYLOAD_CLOUD_EMAIL_DOMAIN_开头、且不以API_KEY结尾的环境变量将其值收集为自定义域名列表并打印日志确认例如PAYLOAD_CLOUD_EMAIL_DOMAIN_1news.example.com PAYLOAD_CLOUD_EMAIL_DOMAIN_2marketing.example.com五、上传缓存默认 24 小时 变更自动失效Payload Cloud 通过 Cloudflare CDN 为 upload 集合提供缓存staticHandler中输出的Cache-Control: public, max-age86400就是默认 24 小时缓存的表现形式。5.1 默认行为与失效机制README 说明了两点默认行为默认对所有 upload 集合缓存 24 小时maxAge 86400秒当某条 upload 记录被更新或删除时缓存会自动失效。从实现看失效分为两层staticHandler靠maxAge让 CDN/浏览器在指定时间内直接命中缓存变更时由src/hooks/uploadCache.ts中注入的afterChange/afterDeletehook 触发一次cache purge向插件配置的 API endpoint默认https://cloud-api.payloadcms.comPOST/api/purge-cachebody 携带{ cacheKey: PAYLOAD_CLOUD_CACHE_KEY, filepath: doc.url, projectID: PAYLOAD_CLOUD_PROJECT_ID }让 Cloudflare 精确清理该文件对应的缓存条目。值得注意的实现细节purge 仅在payloadAPI ! local时执行本地 API 调用不会触发网络 purge且update/delete操作为 fire-and-forgetvoid purge(...)不阻塞主流程purge 需要额外的环境变量PAYLOAD_CLOUD_CACHE_KEY——plugin.ts中cachingEnabled的判定正是uploadCaching ! false !!process.env.PAYLOAD_CLOUD_CACHE_KEY因此没有PAYLOAD_CLOUD_CACHE_KEY时缓存相关 hook 与静态 handler 上的 Cache-Control 头都不会启用doc.url为空时会记录一条 error 日志并提前返回避免无效 purge。六、可选项按需关闭或精细化缓存如果你不需要某项云特性插件支持整体或局部关闭README 中的两种配置形式如下默认全部开启。6.1 整体关闭某一能力payloadCloudPlugin({ storage: false, // Disable file storage email: false, // Disable email delivery uploadCaching: false, // Disable upload caching })types.ts中PluginOptions的类型定义进一步明确了可配置项与默认值选项类型默认说明storagefalse \| undefined开启传false关闭关闭后插件不再修改任何 upload collectionemail{ defaultFromAddress, defaultFromName, skipVerify? } \| false开启关闭或自定义默认发件人skipVerify透传给 nodemailer 适配器uploadCaching{ maxAge?, collections? } \| false开启86400s关闭或精细化配置见 6.2enableAutoRunbooleantrue是否接管config.jobs.autoRun见第七节debugbooleanfalse是否输出额外调试日志并将完整 AWS 错误写入日志endpointstringhttps://cloud-api.payloadcms.com标记为内部开发用途的 API endpoint 覆盖项6.2 上传缓存的精细化配置README 提供了按集合覆盖缓存的完整示例顶层maxAge是全体默认值集合名 keyed 对象中既可以单独设置maxAge单位秒优先级最高也可以用enabled: false对该集合关闭缓存payloadCloudPlugin({ uploadCaching: { maxAge: 604800, // Override default maxAge for all collections collection1Slug: { maxAge: 10, // Collection-specific maxAge, takes precedence over others }, collection2Slug: { enabled: false, // Disable caching for this collection }, }, })对照staticHandler的实现逻辑可以精确看到优先级链maxAge初始化为 86400若顶层配置了maxAge则覆盖全体默认若该集合在collections中有配置则collCacheConfig.maxAge进一步覆盖对应注释 Collection-specific maxAge, takes precedence over others只有collections[slug].enabled ! false且存在PAYLOAD_CLOUD_CACHE_KEY时才会输出Cache-Control头。七、附带能力Jobs 定时任务只在单实例执行README 未展开、但源码完整实现的一个附带能力是Jobs 单实例运行保障见src/plugin.ts。云环境通常多副本部署若每个副本都执行 cron 会导致任务重复。插件通过隐藏 global 实例标识机制协调向 config 注入 slug 为payload-cloud-instance的 hidden globaladmin.hidden: true字段仅一个必填instance文本改写config.jobs.autoRun第一个触发者会生成 24 位随机字符串generateRandomString字母数字全集写入该 global并设置PAYLOAD_CLOUD_JOBS_INSTANCE环境变量后续shouldAutoRun会findGlobal校验自己是否仍是当前持有者不是则清空变量并拒绝运行未配置jobs.autoRun时返回默认 cron job{ cron: * * * * *, limit: 10, queue: default }已有 autoRun 则包装原逻辑函数则 await 后返回其结果。若已有shouldAutoRun插件不会覆盖它。[plugin.spec.ts](https://link.gitcode.com/i/1392a3acde632d3ab978dca8a07c9a04)中的 should always set global instance identifier测试验证了 global 的注入与字段结构。若你不想让插件触碰 jobs 配置可设置enableAutoRun: false。八、测试验证与源码导读本仓库对插件行为有较完整的 vitest 测试集中在packages/payload-cloud/src/plugin.spec.ts与packages/payload-cloud/src/email.spec.ts它们把上文各结论固化成了可回归验证的用例未处于 Payload Cloud 环境未设PAYLOAD_CLOUDtrue时返回未经修改的 config处于云端环境时默认启用云存储验证config.upload.useTempFiles truestorage: false/email: false可正常关闭对应能力默认邮件 transport 指向smtp.resend.comemail依赖的两个环境变量可同时缺席此时不注入邮件已存在 email transport 时不会覆盖打印提示日志自定义defaultFromName/defaultFromAddress生效。对想深入源码的读者建议按以下顺序阅读配置注入packages/payload-cloud/src/plugin.ts执行开关、storage/email/jobs 三块注入逻辑类型契约packages/payload-cloud/src/types.ts全部 PluginOptions 与默认值注释存储三件套src/hooks/beforeChange.ts、src/hooks/afterDelete.ts、src/staticHandler.ts缓存失效src/hooks/uploadCache.ts云认证src/utilities/getStorageClient.ts、src/utilities/refreshSession.ts、src/utilities/authAsCognitoUser.ts九、上线前自查清单最后把本指南的关键前提汇总成一份可操作的 checklist确认运行环境注入了PAYLOAD_CLOUDtrue否则插件整体不生效这是 README 明确的执行边界文件存储要求提供第一组 Cogntio/S3 相关环境变量含必填的PAYLOAD_CLOUD_PROJECT_ID、PAYLOAD_CLOUD_COGNITO_PASSWORD、PAYLOAD_CLOUD_COGNITO_IDENTITY_POOL_ID若需要 CDN 缓存及变更自动失效必须额外提供PAYLOAD_CLOUD_CACHE_KEY邮件功能要求PAYLOAD_CLOUD_EMAIL_API_KEY与PAYLOAD_CLOUD_DEFAULT_DOMAIN同时存在且from域名必须在你有权限的域名白名单内不要忘记自有config.email会优先于 Payload Cloud 邮件服务多副本部署下 Jobs 单实例运行默认开启如不希望插件接管 autoRun 请设置enableAutoRun: false在普通本地项目非 Payload Cloud 托管中引入该插件是安全的——它只会静默返回原 config不会产生副作用。输出文章【免费下载链接】payloadPayload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.项目地址: https://gitcode.com/GitHub_Trending/pa/payload创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门