T3 Code 源码拆解
工程化

20 · 构建、版本与发布

一个 monorepo 如何产出 CLI Server、Web、Electron、Mobile 与 Rust helper,并保持兼容。

不是一个 pnpm build 产出一种应用

根 package.json 用 Vite+ (vp) 作为 workspace 任务编排,但最终产物至少包括:

  • t3 CLI/Server npm 包与 Web 静态资产;
  • Electron macOS DMG、Windows NSIS、Linux AppImage;
  • iOS/Android Expo 原生应用;
  • marketing Web;
  • Rust resource-monitor 平台二进制;
  • T3 Connect relay/Worker 基础设施。

统一仓库允许 contracts 原子升级,发布却必须考虑各端不同节奏:App Store 手机可能几周未更新,而 npx t3@latest 已是新 Server。

根任务图

常用入口包括:

vp i / pnpm install
vp run ... or root scripts
build / typecheck / lint / test / fmt:check
build:desktop / dist:desktop:*
build:resource-monitor / test:resource-monitor
release:smoke

根声明 Node ^24.13.1 与 pnpm 11.10.0,但 README 对运行已发布 CLI 还给出更宽的 Node 22.16+/23.11+/24.10+要求。 开发工具链版本与消费者 runtime 范围可以不同,发布验证必须覆盖真正支持矩阵。

Contracts 先行,但要向后兼容

Monorepo build 可以先生成/检查 contracts,再构建 Server 与客户端。编译通过只证明同一 checkout 兼容;发布需要额外策略:

  • 新字段优先 optional/default;
  • 客户端忽略未知 event/field,但关键 lifecycle 未知时 fail visibly;
  • Server 保持旧 RPC 一段窗口,或提供 capability/version handshake;
  • migration 将本地数据库升级,却不能要求手机同步升级;
  • Provider 协议生成文件与 adapter 变更一同测试。

Server + Web 的打包

npx t3 同时启动本地 backend 和 Web app,意味着 npm 产物要包含可运行 Server、静态 Web assets、必要 migrations 和平台资源。 发布 smoke 应在干净临时 userdata 下启动,检查 health/WebSocket、打开静态入口、列 Provider snapshot,再优雅关闭。

不要在 smoke 中使用真实 ~/.t3:既可能污染用户数据,也会因现存配置让测试假通过。

Electron 打包

scripts/build-desktop-artifact.ts 根据 platform/target/arch 生成安装器。桌面产物还要打包:

  • main/preload/renderer;
  • 内嵌 Server 与 Web assets;
  • 对应平台 resource-monitor;
  • 图标、协议注册、更新 metadata;
  • 原生依赖与签名/公证材料。

构建成功不等于安装可运行,因此 test:desktop-smoke、artifact smoke 和真实安装器测试分层。更新渠道还要保证下载的 renderer 与 backend 是一组兼容产物。

Rust helper 的平台矩阵

native/resource-monitor 用 Cargo --locked --release 构建。Electron/Server 通过 ResourceMonitorBinary 定位正确 OS/arch binary。 发布容易遗漏的情况:macOS arm64/x64、Windows x64/arm64、Linux executable bit、codesign、libc 兼容。

Helper 是可选遥测能力,找不到时主应用应降级;但打包测试仍要验证目标平台本应携带它。

Mobile 发布

Expo/React Native 包含 Swift/Kotlin 自定义模块,不能只依赖 OTA JS 更新。原生 module API 改变时,需要:

  • JS 层 capability/version guard;
  • iOS/Android 同步实现与 static check;
  • 保持旧 binary 能运行新 JS(若使用 OTA);
  • Server contract 仍向后兼容商店旧版。

移动端与 Server 的版本跨度是整个系统最强的兼容性测试。

Provider 协议生成代码

effect-codex-app-server 与 effect-acp 含 _generated Schema/metadata。更新生成文件时应:

  1. 固定上游协议版本/输入;
  2. 将生成 diff 与手写 adapter diff 分开审查;
  3. 运行 decode fixture 与 runtime mapping 测试;
  4. 检查 unknown/optional 字段兼容;
  5. 不手工修生成文件而忘记 generator 来源。

发布前门禁

建议的发布门禁
fmt check lint typecheck unit + integration tests all target builds server / desktop / native smoke version + changelog / notes sign + publish artifacts install / update verification

仓库根脚本已经覆盖多数环节,平台签名和商店提交由外部环境完成。门禁应 fail fast,但不能因为可选 Provider 未登录而失败; 使用 mock/capability snapshot 验证未安装状态。

回滚与数据版本

应用 binary 可以回滚,SQLite migration 通常不可逆。新版本升级数据库后旧 Server 是否还能读,是发布策略必须明确的问题。 如果不支持 downgrade,应在启动时检测 schema version 并给出安全错误,不能让旧 binary 猜测新表结构后写坏数据。

Electron auto-update 也要避免在 Agent 正执行时强制重启;更新 ready 可以提示,实际安装等待用户确认或安全 idle 点。

可迁移经验

  • Monorepo 原子编译不等于部署原子;用最慢更新的客户端定义兼容窗口。
  • 每类产物都需要“能构建”和“安装/启动可用”两层验证。
  • 可选 native helper 在运行时可降级,在打包 pipeline 中仍要强验证。
  • 生成协议代码、手写语义映射和发布版本应作为一个兼容变更审查。
  • 数据库升级与 binary 回滚是不同方向,必须显式声明 downgrade 策略。

On this page