← 返回博客列表
工程实践2026-05-24·6 分钟阅读

描述符 schema 解耦框架 — 为什么 6 字段就够了

UniversalAppDescriptor 6 字段(runtime / build / start / env / pre_deploy / health),不依赖任何具体框架。扫描器、改写器、部署 agent 三方都只看描述符。

做工具最大的诱惑是 — 「我们再加一个字段处理这个特殊情况」。下面是我们设计 UniversalAppDescriptor 时刻意抵制的几个诱惑。

6 字段够了

schema_version: '1.0'
runtime: node                  # 大类
build:                         # 编译命令
  install: npm install
  command: npm run build
start:                         # 启动 + 健康检查
  command: npm start
  port: 3000
  health_path: /healthz
env:                           # 环境变量约定
  required_keys: [DATABASE_URL]
  defaults: { NODE_ENV: production }
pre_deploy: []                 # 数据库迁移等
health: {}                     # 健康检查策略 (Phase 2)

诱惑 1:加 framework 字段

"runtime 太粗,加个 framework=nextjs 不就清楚了吗?" 不行。因为 framework 列表会一直变,而我们的代码(扫描器 / 改写器 / 部署 agent)只能识别一个固定有限的 framework 集合。一旦 framework 字段进 schema,所有代码都得知道每个 framework 长什么样。

替代:framework 信息塞进 detected_stack 字段(scanner 给 UI 用,改写器不读)。改写器只看 runtime+start+build,与 framework 解耦。

诱惑 2:加 deploy_strategy 字段

"用户可能要蓝绿、金丝雀、滚动 — 加个 strategy 字段吧?" 不行。因为 strategy 是 Update 流程的事,不是描述符的事。描述符描述「这个应用长什么样」,不描述「怎么上它」。

诱惑 3:加 dependencies 字段

"应用可能依赖 redis / postgres / kafka,加个 dependencies 列表吧?" 不行。因为依赖配置本来就是 env 字段的工作 — DATABASE_URL=postgres://... / REDIS_URL=redis://...。扫描器不知道你用的是哪个数据库,只知道你需要 DATABASE_URL。

改写器为什么能用同一描述符服务所有 node 项目

因为 node runtime + npm start + port 3000 这三个字段,无论你用 Next.js 还是 Nuxt 还是 Vanilla Express,改写器吐的产物完全一样:.env.production + pm2 ecosystem + nginx vhost。

// pm2 ecosystem.config.js — 改写器从描述符生成
module.exports = {
  apps: [{
    name: '<%= project_slug %>',
    cwd: '<%= server_app_root %>',
    script: 'npm',
    args: 'start',                  // 来自 descriptor.start.command
    env: { NODE_ENV: 'production' },
    instances: 1,
    autorestart: true,
  }]
};

演进策略

v1.0 6 字段就够了。如果未来真需要加,加之前先问:能不能塞进现有字段?如果不能再加,而且要在 schema_version 升 v2.0 时做。永远不要在 v1.x 内悄悄加字段 — 这会破坏向后兼容。

schema 不是越多字段越好,而是越少越好。少 = 易于实现、易于演进、易于约定。

同类阅读

评论功能未启用(需要环境变量 NEXT_PUBLIC_UTTERANCES_REPO=owner/repo)