一个人维护全栈项目:我准备怎样升级 Kita
Kita 当前的版本组合写在 package.json:
1 | Node 22 |
这些数字迟早都会过时。真正需要长期保留的不是“永远使用这一版”,而是每一类升级应该改哪些文件、怎样证明没有破坏数据。
Lockfile 不是不允许升级
package.json 表达允许范围,pnpm-lock.yaml 记录本次解析出的完整依赖树。
开发环境和 CI 都使用:
1 | pnpm install --frozen-lockfile |
这保证同一个 commit 安装相同依赖。要升级时,应该在一个明确 PR 中更新 package 和 lockfile;不应该让部署机器每次自己寻找“今天最新的兼容版本”。
我不会把所有包一起升级
一次升级 30 个 package 的问题不是 diff 太长,而是失败时不知道责任属于谁。
Kita 更适合把升级分成几组:
1 | 工具组 |
同一生态中需要相互匹配的包一起升级,不相关的风险分开。
Node 升级至少有三处
Kita 的 Node 22 不只存在于一行:
1 | .devcontainer/devcontainer.json |
还要核对 @types/node、Corepack/pnpm 行为和 native dependencies,例如 Sharp、SWC。
只改 Dev Container 会造成“本地新、生产旧”;只改 Dockerfile 会造成“CI 通过的不是部署版本”。运行环境升级必须把三处作为一个检查单元。
Next.js 升级先看运行模式
Kita 使用:
- App Router;
- Server Components;
- dynamic routes 和 metadata;
output: "standalone";typedRoutes;- Payload 的
withPayload(); - Next Image remote pattern。
升级 Next 时,除了 pnpm build,还要检查 standalone runner、Payload Admin、dynamic 页面、图片 URL 和 Client Component 交互。
首页的 WebGL 雨滴不一定会被类型检查覆盖;Games Lightbox 的焦点和键盘行为也不一定因为 build 成功就正确。这些需要浏览器 smoke。
Payload 升级要同时看代码和数据库
Payload 相关包应保持兼容版本,不单独把 payload 升级而留下旧的 @payloadcms/db-postgres、@payloadcms/next 或 rich text adapter。
升级后至少执行:
1 | pnpm payload:types |
然后判断 Collection schema 是否真的变化。依赖版本变化不自动等于需要新 migration;但如果生成的 schema 或 adapter 行为改变,必须在空 PostgreSQL 和生产数据副本上验证 migration 链。
Kita 还有一项普通 Next build 不会覆盖的路径:production runner 会直接加载 Payload config 并运行 migration。7 月 3 日的 503 已经证明,这条路径需要单独检查。
PostgreSQL 不能当作普通镜像 tag 更新
Compose 当前固定 postgres:16。升级到新的 major 版本不是把 16 改成另一个数字就结束。
数据库 major upgrade 需要:
- 完整 dump;
- 独立新实例;
- restore;
- 执行 Payload 查询与写入;
- 检查 migration status;
- 页面和 Admin smoke;
- 明确回退到旧实例的方法。
Kita 目前连 PostgreSQL 16 的完整 restore drill 都尚未完成,因此没有理由为了追新版本提前扩大这个风险。
OpenList 是另一条发布节奏
OpenList 使用独立 Coolify Application 和固定镜像版本。升级它不应该触发 Kita build、Payload migration 或 PostgreSQL 变更。
它自己的升级清单是:
1 | 备份 OpenList data |
如果 OpenList 回滚,Kita 不需要一起回滚。这正是当初没有把它塞进 Kita Compose 的长期收益。
一次依赖升级 PR 的实际顺序
我希望保持下面这种节奏:
1 | git fetch origin |
涉及数据库或 storage adapter 时,还要在发布前备份,并把生产 smoke 和回滚条件写进 PR。
Security Patch 与普通升级不是同一优先级
如果 Next、Payload、OpenList 或基础镜像出现影响当前用法的安全更新,应缩小范围尽快处理。普通 feature release 则可以等到项目有明确收益。
判断顺序不是“有没有新版本”,而是:
1 | 当前版本是否受影响 |
文档也会随升级过期
Kita 已经发生过文档与源码不一致:早期文档说不使用 named volume,后来 Windows 性能数据让 .next 和 node_modules 成为有边界的例外;测试数量和正常启动命令也曾漂移。
因此升级完成后,事实顺序应该是:
1 | 当前源码与配置 |
不能为了让旧文章继续正确,反过来让源码保持旧决定。
我更在意可回退,而不是永远最新
一个人维护项目时,最危险的不是落后一个 minor version,而是同时升级应用、数据库、容器和内容模型,最后没有一个可以单独回退的节点。
Kita 以后可以继续更新,但每次只扩大一个已知边界。升级应该留下 commit、PR、检查结果和数据恢复路径,而不是只在 package.json 里留下几个更大的数字。
下一篇讨论 Self-host 最容易被忽略的部分:Kita 的资源、成本与单点故障。


















