Chapter 05

让缓存跨机器共享

本地缓存只帮你自己;远程缓存让你的 CI 构建、同事的本地构建、生产部署共享同一份产物——"我已经 build 过了,你不用再跑"。这是 Turborepo 在大团队里真正的杀招。

远程缓存的本质

本地缓存:       apps/web/.turbo/cache/
远程缓存:       https://my-remote-cache.vercel.app/v8/artifacts/

任务执行时:
  1. 算 hash xxx
  2. 查本地 .turbo/cache/xxx.tar.zst → 有就用
  3. 查远程 GET /v8/artifacts/xxx → 有就下载 + 缓存到本地
  4. 都没有 → 执行任务
  5. 执行后:写本地 + PUT 到远程

协议标准化:Turbo 的远程缓存 API 是开放的(HTTP + tar.zst),任何服务实现它就能接。

方案一:Vercel Remote Cache(免费)

pnpm turbo login          # 浏览器登录 Vercel
pnpm turbo link           # 关联当前仓库到一个 Vercel team

完成后:

GitHub Actions 配置

- env:
    TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
    TURBO_TEAM: my-team-slug
  run: pnpm turbo run build

首次拉代码的开发者:

pnpm install
pnpm turbo login
pnpm turbo run build
# Checking for remote cache... @myorg/ui:build: remote cache hit!
# 直接下载 CI 构建的产物,不用自己 build
真实体验:新人 onboarding 时间从 10 分钟变 30 秒
Git clone + pnpm install 后 turbo build 直接拉 CI 产物,不用本地 20 秒 build——实测小团队上 Turbo 远程缓存,上手速度翻几倍。

方案二:自建 Remote Cache

Vercel 不用,或数据敏感不想让第三方存——自建。几个选择:

ducktors/turborepo-remote-cache

# Node.js 实现,存 S3/R2/Azure Blob/本地
docker run -d \
  -p 3000:3000 \
  -e TURBO_TOKEN=my-secret \
  -e STORAGE_PROVIDER=s3 \
  -e S3_BUCKET=turbo-cache \
  -e S3_ACCESS_KEY=... \
  -e S3_SECRET_KEY=... \
  ducktors/turborepo-remote-cache

Cloudflare Workers 方案

把缓存直接放 Cloudflare R2(S3 兼容),用 Worker 做签名校验——全球分布,延迟 50ms 以内,免费额度极高。

配置客户端

.turbo/config.json 或 env
TURBO_API=https://my-cache.example.com
TURBO_TOKEN=my-secret
TURBO_TEAM=myorg
// .turbo/config.json(推荐,进 git)
{
  "apiUrl": "https://my-cache.example.com",
  "teamSlug": "myorg"
}

缓存签名(安全必做)

{
  "remoteCache": {
    "signature": true
  }
}
# CI
- env:
    TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
    TURBO_TEAM: myorg
    TURBO_REMOTE_CACHE_SIGNATURE_KEY: ${{ secrets.TURBO_SIGNATURE_KEY }}
  run: pnpm turbo run build

上传时每个 tar 带 HMAC,下载后用同样的 key 验证——即使缓存服务器被攻破、别人投放恶意 tar,本地会拒绝。生产必开

只读 / 只写模式

# 只从远程读,不上传(防止本地构建污染 CI 缓存)
pnpm turbo run build --remote-cache-read-only

# CI 可以读写,开发者 PR 机器只读

策略:

  1. CI 在 main 分支:读写
  2. CI 在 PR 分支:只读(防止污染主分支缓存)
  3. 开发者本地:默认只读,避免影响团队

缓存 hit 率统计

pnpm turbo run build --summarize
# 生成 .turbo/runs/xxx.json,含每个任务的 cacheState
{
  "taskId": "@myorg/web#build",
  "cacheState": { "local": false, "remote": true },
  "executionTime": 42,
  "cacheSource": "REMOTE"
}

上传到监控系统,统计命中率——对优化 CI 时间很有指导。

远程缓存带来的风险

缓存污染
有人本地 build 时环境异常,产物里有 bug,上传到远程——之后所有人命中这个坏缓存,线上翻车。

Vercel 部署的集成

把项目托管到 Vercel,且关联同一 team slug——构建时自动启用 Remote Cache,不用配任何环境变量。

实际效果:

1. 你 push 到 GitHub
2. GitHub Actions 跑 turbo build,上传 hash=xxx 的缓存到 Vercel
3. Vercel 收到 webhook,开始部署
4. Vercel 内部也跑 turbo build,发现 hash=xxx 已经有缓存
5. 直接复用,跳过构建,Deploy 完成时间 30 秒

如果没有 Turbo:同样代码在 CI 和 Vercel 各 build 一次,double 开销。

Ignored Build Step

# vercel.json
{
  "ignoreCommand": "npx turbo-ignore"
}

turbo-ignore 判断当前 PR 是否影响这个项目——不影响则跳过整个 Vercel 部署。monorepo 里 5 个 app,改 docs 不用重部署 web。

清远程缓存

# Vercel 上
pnpm turbo unlink
# 本地断开,不再上传

# Vercel dashboard → Team Settings → Caching → Invalidate Cache
# 清所有远程缓存

# 自建服务直接清数据库/S3 bucket

限制

实战对比

场景纯本地+ Remote Cache
新人 clone + build25 秒8 秒
CI PR 开头首次3 分钟30 秒
CI PR 改 1 个包3 分钟20 秒
Vercel 部署3 分钟30 秒(复用 CI 产物)
开发者切分支20 秒5 秒(拉别人的产物)

本章小结