Turborepo缓存配置与优化Skill turborepo-caching

这个技能用于配置和优化Turborepo的缓存机制,包括本地和远程缓存,以提高monorepo项目的构建效率。适用于设置Turborepo项目、配置构建管道、实现远程缓存、优化CI/CD性能等场景。关键词:Turborepo, 缓存, monorepo, 构建优化, CI/CD, 远程缓存。

DevOps 0 次安装 0 次浏览 更新于 3/22/2026

name: turborepo-caching description: 配置Turborepo以实现高效的monorepo构建,包括本地和远程缓存。适用于设置Turborepo、优化构建管道或实现分布式缓存。

Turborepo 缓存

Turborepo构建优化的生产模式。

何时使用此技能

  • 设置新的Turborepo项目
  • 配置构建管道
  • 实现远程缓存
  • 优化CI/CD性能
  • 从其他monorepo工具迁移
  • 调试缓存未命中

核心概念

1. Turborepo 架构

Workspace Root/
├── apps/
│   ├── web/
│   │   └── package.json
│   └── docs/
│       └── package.json
├── packages/
│   ├── ui/
│   │   └── package.json
│   └── config/
│       └── package.json
├── turbo.json
└── package.json

2. 管道概念

概念 描述
dependsOn 必须先完成的任务
cache 是否缓存输出
outputs 要缓存的文件
inputs 影响缓存键的文件
persistent 长时间运行的任务(开发服务器)

模板

模板 1: turbo.json 配置

{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": [".env", ".env.local"],
  "globalEnv": ["NODE_ENV", "VERCEL_URL"],
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**"],
      "env": ["API_URL", "NEXT_PUBLIC_*"]
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": ["coverage/**"],
      "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts"]
    },
    "lint": {
      "outputs": [],
      "cache": true
    },
    "typecheck": {
      "dependsOn": ["^build"],
      "outputs": []
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "clean": {
      "cache": false
    }
  }
}

模板 2: 包特定管道

// apps/web/turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "extends": ["//"],
  "pipeline": {
    "build": {
      "outputs": [".next/**", "!.next/cache/**"],
      "env": ["NEXT_PUBLIC_API_URL", "NEXT_PUBLIC_ANALYTICS_ID"]
    },
    "test": {
      "outputs": ["coverage/**"],
      "inputs": ["src/**", "tests/**", "jest.config.js"]
    }
  }
}

模板 3: 使用Vercel的远程缓存

# 登录Vercel
npx turbo login

# 链接到Vercel项目
npx turbo link

# 使用远程缓存运行
turbo build --remote-only

# CI环境变量
TURBO_TOKEN=your-token
TURBO_TEAM=your-team
# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main]
  pull_request:

env:
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
  TURBO_TEAM: ${{ vars.TURBO_TEAM }}

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: "npm"

      - name: 安装依赖
        run: npm ci

      - name: 构建
        run: npx turbo build --filter='...[origin/main]'

      - name: 测试
        run: npx turbo test --filter='...[origin/main]'

模板 4: 自托管远程缓存

// 自定义远程缓存服务器(Express)
import express from "express";
import { createReadStream, createWriteStream } from "fs";
import { mkdir } from "fs/promises";
import { join } from "path";

const app = express();
const CACHE_DIR = "./cache";

// 获取工件
app.get("/v8/artifacts/:hash", async (req, res) => {
  const { hash } = req.params;
  const team = req.query.teamId || "default";
  const filePath = join(CACHE_DIR, team, hash);

  try {
    const stream = createReadStream(filePath);
    stream.pipe(res);
  } catch {
    res.status(404).send("Not found");
  }
});

// 放置工件
app.put("/v8/artifacts/:hash", async (req, res) => {
  const { hash } = req.params;
  const team = req.query.teamId || "default";
  const dir = join(CACHE_DIR, team);
  const filePath = join(dir, hash);

  await mkdir(dir, { recursive: true });

  const stream = createWriteStream(filePath);
  req.pipe(stream);

  stream.on("finish", () => {
    res.json({
      urls: [`${req.protocol}://${req.get("host")}/v8/artifacts/${hash}`],
    });
  });
});

// 检查工件是否存在
app.head("/v8/artifacts/:hash", async (req, res) => {
  const { hash } = req.params;
  const team = req.query.teamId || "default";
  const filePath = join(CACHE_DIR, team, hash);

  try {
    await fs.access(filePath);
    res.status(200).end();
  } catch {
    res.status(404).end();
  }
});

app.listen(3000);
// turbo.json 用于自托管缓存
{
  "remoteCache": {
    "signature": false
  }
}
# 使用自托管缓存
turbo build --api="http://localhost:3000" --token="my-token" --team="my-team"

模板 5: 过滤和范围限定

# 构建特定包
turbo build --filter=@myorg/web

# 构建包及其依赖
turbo build --filter=@myorg/web...

# 构建包及其依赖项
turbo build --filter=...@myorg/ui

# 构建自main分支以来的更改包
turbo build --filter='...[origin/main]'

# 构建目录中的包
turbo build --filter='./apps/*'

# 组合过滤器
turbo build --filter=@myorg/web --filter=@myorg/docs

# 排除包
turbo build --filter='!@myorg/docs'

# 包含更改的依赖项
turbo build --filter='...[HEAD^1]...'

模板 6: 高级管道配置

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"],
      "inputs": ["$TURBO_DEFAULT$", "!**/*.md", "!**/*.test.*"]
    },
    "test": {
      "dependsOn": ["^build"],
      "outputs": ["coverage/**"],
      "inputs": ["src/**", "tests/**", "*.config.*"],
      "env": ["CI", "NODE_ENV"]
    },
    "test:e2e": {
      "dependsOn": ["build"],
      "outputs": [],
      "cache": false
    },
    "deploy": {
      "dependsOn": ["build", "test", "lint"],
      "outputs": [],
      "cache": false
    },
    "db:generate": {
      "cache": false
    },
    "db:push": {
      "cache": false,
      "dependsOn": ["db:generate"]
    },
    "@myorg/web#build": {
      "dependsOn": ["^build", "@myorg/db#db:generate"],
      "outputs": [".next/**"],
      "env": ["NEXT_PUBLIC_*"]
    }
  }
}

模板 7: 根package.json设置

{
  "name": "my-turborepo",
  "private": true,
  "workspaces": ["apps/*", "packages/*"],
  "scripts": {
    "build": "turbo build",
    "dev": "turbo dev",
    "lint": "turbo lint",
    "test": "turbo test",
    "clean": "turbo clean && rm -rf node_modules",
    "format": "prettier --write \"**/*.{ts,tsx,md}\"",
    "changeset": "changeset",
    "version-packages": "changeset version",
    "release": "turbo build --filter=./packages/* && changeset publish"
  },
  "devDependencies": {
    "turbo": "^1.10.0",
    "prettier": "^3.0.0",
    "@changesets/cli": "^2.26.0"
  },
  "packageManager": "npm@10.0.0"
}

调试缓存

# 干运行以查看将运行的内容
turbo build --dry-run

# 带有哈希的详细输出
turbo build --verbosity=2

# 显示任务图
turbo build --graph

# 强制不使用缓存
turbo build --force

# 显示缓存状态
turbo build --summarize

# 调试特定任务
TURBO_LOG_VERBOSITY=debug turbo build --filter=@myorg/web

最佳实践

应该做的

  • 定义明确的输入 - 避免缓存失效
  • 使用工作区协议 - "@myorg/ui": "workspace:*"
  • 启用远程缓存 - 在CI和本地共享
  • 在CI中过滤 - 仅构建受影响的包
  • 缓存构建输出 - 非源文件

不应该做的

  • 不要缓存开发服务器 - 使用 persistent: true
  • 不要在env中包含秘密 - 使用运行时环境变量
  • 不要忽略dependsOn - 导致竞态条件
  • 不要过度过滤 - 可能错过依赖项

资源