告别缓慢构建:在 GitLab CI 中集成自建 Turbo 远程缓存的深度实践
在大型 Monorepo 项目中,构建效率直接影响开发者的幸福感。虽然 Turborepo 默认提供了本地缓存,但在 GitLab CI 的短暂运行环境中,由于每个 Job 的环境通常是隔离且销毁的,本地缓存无法跨任务共享。
虽然 Vercel 提供了官方的远程缓存服务,但出于成本、网络延迟或数据隐私的考虑,许多团队选择自建 Turbo 缓存服务器(例如使用 ducktors/turborepo-remote-cache 等开源方案)。本文将详细介绍如何在 .gitlab-ci.yml 中完成这一集成。
1. 核心环境变量配置
要让 Turborepo 识别并连接到你的自建服务,需要配置以下三个核心环境变量。建议将这些变量配置在 GitLab 项目的 Settings > CI/CD > Variables 中,并勾选 "Mask variable" 以保证安全。
TURBO_TOKEN: 自定义服务鉴权所需的 Token。TURBO_TEAM: 你的团队名称(自建服务通常作为路径一部分或校验字段,可随意填写但必须存在)。TURBO_REMOTE_CACHE_URL: 自建缓存服务的 API 地址(例如https://turbo.your-company.com)。
注意:从 Turborepo v1.6.0 开始,可以通过
TURBO_REMOTE_CACHE_URL直接指定服务端地址,不再强制要求复杂的 API 代理。
2. 完整 .gitlab-ci.yml 示例
以下是一个典型的集成示例,包含了依赖安装、构建任务以及缓存生命周期的管理。
stages:
- install
- build
# 定义全局变量映射
variables:
# 告诉 Turbo 使用远程缓存服务器地址
TURBO_API: $TURBO_REMOTE_CACHE_URL
# 传入鉴权 Token
TURBO_TOKEN: $TURBO_TOKEN
# 传入团队名称
TURBO_TEAM: $TURBO_TEAM
default:
image: node:18-alpine
# 传统的 node_modules 缓存,用于加速 npm install
cache:
key:
files:
- pnpm-lock.yaml # 根据你使用的包管理器调整
paths:
- .pnpm-store
# 安装依赖阶段
install_dependencies:
stage: install
script:
- corepack enable
- pnpm install --frozen-lockfile
artifacts:
paths:
- node_modules/
expire_in: 1 hour
# 构建阶段(核心部分)
build_project:
stage: build
script:
# 使用 npx turbo build 执行构建
# --remote-only: 在 CI 中建议只使用远程缓存,避免本地磁盘 I/O 干扰
# --summarize: 生成构建报告,方便排查缓存未命中的原因
- npx turbo build --remote-only --summarize
artifacts:
paths:
- "apps/**/dist"
- "packages/**/dist"
- ".turbo/runs" # 存放 summarize 报告
expire_in: 1 day
3. 关键参数解析
为什么使用 --remote-only?
在 GitLab CI 环境中,本地磁盘是临时的。虽然 Turbo 会尝试读写 .turbo/cache,但在没有持久化缓存卷的情况下,这些写入是徒劳的。通过 --remote-only 标志,你可以强制 Turbo 跳过本地磁盘缓存的读写,直接与远程 API 通信,这在某些 I/O 受限的容器环境中能略微提升速度。
环境变量的优先级
如果在项目中已经存在 turbo.json,确保里面没有硬编码任何与 Vercel 相关的配置。GitLab CI 中的环境变量会覆盖本地配置文件中的缺省设置。
处理鉴权失败
如果你自建的服务使用了自签名证书或特殊的路径,请确保在 CI 镜像中信任了相应的 CA 证书,否则 Turbo 会因为 SSL 校验失败而退回到完全不使用缓存的状态。
4. 如何验证缓存是否生效?
在 GitLab CI 的 Job 日志中,观察 turbo build 的输出。
- Cache Hit (Remote): 表示成功从自建服务下载了缓存。
- Cache Miss: 表示未找到缓存,正在执行任务并尝试上传结果。
- Remote Caching Error: 如果出现此提示,请检查
TURBO_REMOTE_CACHE_URL是否可访问,以及TURBO_TOKEN是否正确。
5. 进阶:限制分支缓存
有时你可能不希望 feature 分支的缓存污染 master 分支。虽然 Turborepo 默认会根据输入文件的 Hash 值来隔离缓存,但如果你想在自建服务端做物理隔离,可以利用 GitLab CI 的预定义变量:
variables:
# 根据分支动态改变 Team,从而在自建服务端实现简单的隔离逻辑
TURBO_TEAM: "my-project-$CI_COMMIT_REF_SLUG"
总结
通过在 GitLab CI 中集成自建 Turbo 远程缓存,我们可以将 Monorepo 的构建时间从分钟级压缩到秒级。这不仅节省了 GitLab Runner 的计算资源(和钱),更极大地提升了开发者的反馈效率。
避坑指南:
- 确保自建服务的存储后端(S3/Local)空间充足。
- 确保 GitLab Runner 到缓存服务器的网络带宽足够大,否则下载大体积缓存(如含有大量 SourceMap 的 dist)可能比直接构建更慢。