远程缓存的本质
本地缓存: 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
完成后:
- 本地开发用户自动带
~/.config/turborepo/auth.json里的 token - CI 需要手动配
TURBO_TOKEN和TURBO_TEAM环境变量 - 免费额度:每月 10GB 缓存 + 200 个 CI runner minutes——个人/小团队够用
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 后
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 机器只读
策略:
- CI 在 main 分支:读写
- CI 在 PR 分支:只读(防止污染主分支缓存)
- 开发者本地:默认只读,避免影响团队
缓存 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,上传到远程——之后所有人命中这个坏缓存,线上翻车。
有人本地 build 时环境异常,产物里有 bug,上传到远程——之后所有人命中这个坏缓存,线上翻车。
- 解决 1:CI 只读缓存,写入只从 main 分支 CI
- 解决 2:出事后
turbo prune-cache清相关 hash - 解决 3:签名 key 泄漏要轮换
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
限制
- 缓存产物大小 > 1GB 的任务不适合远程缓存——上传下载成本超过 build 本身
- 网络差的地区(离 Vercel 区域远)可能比本地 build 慢——考虑区域 CDN
- 非确定性任务(随时间变化的输出)缓存会污染
实战对比
| 场景 | 纯本地 | + Remote Cache |
|---|---|---|
| 新人 clone + build | 25 秒 | 8 秒 |
| CI PR 开头首次 | 3 分钟 | 30 秒 |
| CI PR 改 1 个包 | 3 分钟 | 20 秒 |
| Vercel 部署 | 3 分钟 | 30 秒(复用 CI 产物) |
| 开发者切分支 | 20 秒 | 5 秒(拉别人的产物) |
本章小结
- 远程缓存 = 跨机器跨人共享构建产物,API 协议开放
- Vercel Remote Cache 免费额度足够小团队,
turbo login + turbo link一键接入 - 自建方案 ducktors/turborepo-remote-cache + S3/R2,适合隐私敏感场景
signature: true+ secret key 防缓存投毒,生产必开- PR 分支只读 + main 分支读写,防缓存污染