WEBKT

告别缓慢构建:在 GitLab CI 中集成自建 Turbo 远程缓存的深度实践

4 0 0 0

在大型 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 的计算资源(和钱),更极大地提升了开发者的反馈效率。

避坑指南

  1. 确保自建服务的存储后端(S3/Local)空间充足。
  2. 确保 GitLab Runner 到缓存服务器的网络带宽足够大,否则下载大体积缓存(如含有大量 SourceMap 的 dist)可能比直接构建更慢。
DevOps 极客 GitLab CITurborepo远程缓存

评论点评