Skip to Content

部署

使用 OpenNext 与受版本控制的 custom-worker 入口,将模板部署到 Cloudflare Workers。开发者预览 展示了商业模板的一种配置。你的部署需要自己的 Cloudflare 资源与密钥;部署成功不能验证支付、邮件、OAuth 或存储供应商。

选择应用与目标

构建前,在 src/config/product.ts 选择应用组合。基本资料不需要支付供应商。随附声明选择新的个人购买,缺失供应商时仍不可用。全新纯核心应用选择 productCompositions.core。Docs、Blog、分析与反馈附件分别配置。

应用范围与发布目标应分别选择:

选择含义
dev使用受版本控制的 wrangler.toml,本地 Worker 端口 8787;仅构建
preview私有配置中的显式 [env.preview],通常是名为 <name>-preview 的 Worker
production私有配置的顶层 Worker 与绑定;写入需要 --confirm production
候选--candidate 标签,将 Worker 与 D1 回执关联到保留的源码及锁文件

开发者预览所用域名可能属于顶层 Worker。应根据实际配置归属选择命令,不能只看站点描述中的“预览”。APP_URL 标识公开 origin,不选择 Worker 或数据库。

准备隔离候选

按安装指南使用 Node.js 24 LTS 与 npm 10.9.2。准备独立、完整的源码目录,包含预期修改、package-lock.json、内容与迁移。保留这些输入,确保候选标签可追溯至实际源码。发布当前工作时,应包含预期的未提交或新增文件;单个 Git 提交可能遗漏它们。

源码快照应排除本地数据库、日志、生成输出、缓存以及私有环境/配置文件。在该目录安装独立的实体依赖:

npm ci

OpenNext 打包时会写入依赖。不要共享或符号链接正在运行的开发目录中的 node_modules。命名本地 Next 实例不提供 OpenNext 安装隔离。完成干净安装后,只在此候选中准备所选目标的私有配置。

准备私有配置

cp wrangler.remote.example.toml wrangler.remote.toml

用自己的账户、Worker 名称、路由/自定义域名及 D1/KV/R2 绑定替换所选环境的占位值。保留 main = "custom-worker.ts" 与生成资源绑定。顶层 routes 放在 TOML section 标题之前;预览路由归 [env.preview]。受版本控制的 wrangler.toml 保持模板安全值。

保留示例的顶层 keep_names = false。Wrangler 保留名称的打包转换可能向主题初始化器注入辅助函数,随后序列化到页面,导致浏览器报 __name is not defined。已有私有配置也必须在打包和部署前设置此值。

为所选 D1 绑定设置相对于私有配置目录的 migrations_dir = "drizzle",省略 migrations_table 或使用 "d1_migrations"。路径必须指向此候选的迁移。预览绑定与变量必须在该环境显式声明,不能假定继承顶层值。

默认配置为 wrangler.remote.toml。所有发布命令支持 --config FILE 或 WRANGLER_REMOTE_CONFIG_PATH,CLI 覆盖环境变量。整个发布过程使用同一配置、目标与候选。

配置构建输入与运行时密钥

输入归属
公开组合与品牌src/config/product.ts;修改后重建
远端账户、路由与资源身份私有 Wrangler 配置
非密钥 Worker 设置所选配置的 [vars] 或 [env.preview.vars],包括正确 HTTPS APP_URL
构建时 Next.js 环境隔离候选的构建环境;公开值与目标保持一致
Worker 运行时密钥Cloudflare secret 存储;仅上传预期 Worker 密钥
D1/seed 辅助凭据按目标使用 .env.cloudflare.preview 或 .env.cloudflare
仅本地值本地 app 用 .env.local,本地 Worker 用 .dev.vars.dev

远端辅助环境文件不会自动上传为 Worker secrets。运行时密钥不提供 Next.js 公开构建时值。持续使用的环境应保持 AUTH_SECRET 稳定,使用目标的可信 origin,并提供所选操作所需的运营密钥。仅配置确实准备运行的供应商。生产 Worker 不提供开发自动登录。

使用 Wrangler 登录或权限范围适当的 CLOUDFLARE_API_TOKEN 认证。未显式配置令牌时,D1 发布使用已保存的 Wrangler 登录。默认辅助环境文件可选;显式选择的 --env-file 必须存在。需要辅助输入时,从 .env.cloudflare.example 为所选目标准备:

npm exec -- wrangler whoami

仅上传密钥时,创建包装命令读取的私有 dotenv 文件:.env.preview.secrets 或 .env.production.secrets。只包含 Worker 运行时密钥,不上传 Cloudflare API 令牌或辅助凭据。这些文件不得进入源码归档或版本控制。

# Preview target: reads .env.preview.secrets npm run secrets:upload:preview # Top-level target: reads .env.production.secrets npm run secrets:upload:production -- --confirm production

管理密钥要求目标 Worker 已存在。新服务应先通过正常部署流程创建,再配置密钥并验证运行时就绪。上传密钥可独立于源码候选改变正在运行的 Worker。使用 secrets:list:preview 或 secrets:list:production 只查看名称,不显示值。除非明确打算产生真实效果,否则预览环境不要配置真实支付或外发邮件。

验证并发布

从准备好的候选目录运行,将 release-001 替换为选定 ID。规划读取配置并验证输入,但不读取凭据文件或连接 Cloudflare:

npm run cf:deploy:preview -- --candidate release-001 --dry-run npm run db:release:d1:preview -- --candidate release-001 --dry-run

针对所选输入运行本地静态检查与只读配置检查:

npm exec velite npm run check npm run adoption:check -- --lane preview

接入诊断检查环境的本地输入文件,不检查 Worker 实际环境或远端结构。退出 0 仍可包含未验证项。源码与配置未改变时,可复用适用且已通过的检查。

预览目标先发布代码所需的有序 D1 迁移,再构建部署:

npm run db:release:d1:preview -- --candidate release-001 npm run cf:deploy:preview -- --candidate release-001

顶层目标使用对应的生产包装命令:

npm run db:release:d1 -- --candidate release-001 --confirm production npm run cf:deploy -- --candidate release-001 --confirm production

只验证已完整应用的迁移历史时,使用 --skip-apply 而不写入。D1 发布不执行 seed。需要初始化时,等运行时配置就绪后使用显式远端初始化流程。

cf:deploy* 已在部署前构建候选。只需构建时使用 cf:build:preview -- --candidate release-001 或 cf:build -- --candidate release-001;之后部署会重新构建。无需每次部署前再单独预构建。

已有数据库

远端 D1 发布使用原生有序 SQL 迁移(包括数据迁移),验证历史、索引与外键。接受空数据库,或与仓库 d1_migrations 历史准确匹配的连续前缀。已有表但历史缺失、不属于此链或存在缺口时会被拒绝。

面对历史未知的已有数据库,应保留数据,确认迁移来源,或另行设计迁往新库的流程。不要用结构推送、重置或编造“已应用”标记绕过拒绝。迁移中断可能保留之前成功的文件;决定下一步前先检查远端历史。没有自动 D1 回滚。

验证已部署候选

记录 Cloudflare 返回的实际 Worker 版本与部署 HTTPS 地址。观察一次运行时健康情况,再针对明确 origin 运行公开浏览器冒烟检查:

npm run health:example -- --origin https://your-preview.example.com PW_BASE_URL=https://your-preview.example.com npm run test:smoke:preview

生产冒烟包装命令同样要求 PW_BASE_URL。这些远端命令复用已部署服务,不初始化或重置数据库;验证环境未安装 Playwright Chromium 时需先安装。

当前公开冒烟检查覆盖首页、登录、定价、Docs、安装及隐藏贡献者指南路由。它预期已选择 Docs 与新购买导航,但结账不可用。核心部署有意让定价返回 404;请使用匹配该组合的检查,不要将预期缺失当作部署失败。公开冒烟检查不验证登录后资源、管理员操作、支付确认、邮件投递或定时执行。

健康接口只提供有限运行时/数据库观察。健康响应成功不能证明完整迁移历史或业务就绪。写入流程应使用自己的隔离测试数据与账户,外部副作用需有意配置。

结果、回滚与恢复

构建/部署与 D1 尝试在候选目录 .cache/release-results/ 下分别写入回执。在发布记录中保留源码、配置身份、候选 ID、前后 Worker 版本 ID 与回执位置。passed 仅适用于对应阶段;skipped 与 unverified 不表示成功。响应丢失或阶段保留 running 表示远端效果可能未知。

发布前,检查并保留已有部署信息:

npm exec -- wrangler deployments list --config wrangler.remote.toml --env preview

恢复先前验证过的 Worker 版本前,先确认它仍兼容当前 D1 结构与绑定,再使用明确版本 ID:

npm exec -- wrangler rollback PREVIOUS_VERSION_ID --config wrangler.remote.toml --env preview --message "Restore the previous verified application"

顶层 Worker 的两条命令都省略 --env preview。回滚改变已部署 Worker 版本,不撤销 D1 迁移、数据写入或已完成的外部效果。回滚前检查密钥与绑定兼容性,再复测健康和受影响浏览器流程。部署成功不代表数据库恢复或回滚演练已完成。

将主机名迁移到独立 Worker 时,保留原 Worker、数据库与密钥。自定义域名和 zone Worker 路由是独立映射:trigger 命令可能移动自定义域名,但已有 hostname/* 路由仍调用原 Worker。任何失败后都应读回两种映射。Worker 版本回滚不会恢复主机名归属。

源码提供 node scripts/worker-domain.js --help,用于有限域名切换或路由回滚。将已核实的账户、zone、域名和路由 ID,以及两个 Worker 名称,保存在根目录被忽略的 wrangler.routes.private.json。--config FILE --direction forward|rollback 生成只读远端计划;审阅后才添加 --execute。命令检查当前归属,只改变所选主机名的两种映射,再读回验证。配置示例与部分失败恢复见源码 scripts/.docs/operational-runbooks.md#worker-domain-cutover。路由成功后仍需 HTTPS 与应用检查;它不代表数据库恢复或完整回滚演练。

失败下一步
缺少目标/候选,或配置身份冲突修正命令/配置,再运行 --dry-run;工具在产生效果前拒绝
OpenNext 依赖隔离被拒绝在候选自己的实体 node_modules 中按锁文件安装,不修改共享安装
Cloudflare 认证或权限失败检查所选账户与令牌权限范围,不输出凭据
自定义域名已移动,但旧 Worker 仍响应重试或恢复路由前,检查独立 zone 路由及两者当前归属
D1 历史未知或应用中断保留数据,继续写入前检查原生历史
Worker 已部署,但登录/健康不可用分别检查运行时密钥名称、origin、所选绑定与迁移结果
页面加载但浏览器报 __name is not defined按远端示例设置顶层 keep_names = false,重新打包部署,验证初始及持久化主题选择
冒烟检查拒绝启动提供 PW_BASE_URL 与已安装浏览器,确认测试预期的组合
本地构建中断留下屏蔽的变量文件在原候选目录运行下述恢复命令
node scripts/run-opennext-command.js restore

这只恢复该目录中不再活跃且有效的 .dev.vars* 暂存。清单缺失、所有者仍活跃或文件冲突时,保留现场供人工处理。它不恢复依赖、Worker 版本、密钥或数据库。

CI 遵循相同顺序:隔离的锁定安装、私有目标输入、适用检查、有序迁移、构建部署,再验证明确 origin。需要时将回执保持私有,不发布配置值或供应商错误响应体。