Допустим, ваш билд фронтенда длится 12 минут, а бекенд и фронтенд в разных репозиториях. Общий код дублируется, задачи CI выполняются последовательно. Это типичная ситуация, которую мы решаем настройкой Turborepo monorepo. Мы сталкивались с проектами, где сборка занимала 30 минут, и Turborepo сократил это до 5. Правильная конфигурация сокращает время сборки в 3–5 раз за счёт параллелизации и кеширования. После внедрения клиенты сокращают затраты на CI-инфраструктуру на существенную сумму. Мы гарантируем, что ваш проект будет собираться быстрее.
Когда стоит выбирать Turborepo?
npm/yarn/pnpm workspaces уже дают monorepo-структуру, но Turborepo добавляет параллельный запуск с учётом зависимостей, инкрементальный кеш (локальный и удалённый) и граф задач. Если проект небольшой (2–3 пакета) — workspaces достаточно. При 5+ пакетах и CI/CD Turborepo начинает экономить реальное время. Сравнение: при 10 пакетах Turborepo в 4 раза быстрее ручной параллелизации за счёт автоматического вывода порядка сборки.
Почему Turborepo, а не Nx?
Turborepo легче: нет необходимости в генераторах кода и плагинах. Достаточно turbo.json и workspace-протокола. Это идеальный выбор для команд, которые хотят monorepo без избыточности. Nx предлагает больше функций, но Turborepo выигрывает в простоте настройки и скорости работы.
Структура проекта
my-project/
├── apps/
│ ├── web/ # Next.js фронтенд
│ ├── admin/ # Vite + React admin panel
│ └── api/ # Node.js/Express backend
├── packages/
│ ├── ui/ # общие React-компоненты
│ ├── config/
│ │ ├── eslint/ # конфиг ESLint
│ │ ├── typescript/ # базовые tsconfig
│ │ └── tailwind/ # tailwind preset
│ ├── utils/ # общие утилиты (formatDate, etc.)
│ └── types/ # общие TypeScript-типы
├── package.json # workspaces declaration
├── turbo.json # конфигурация Turborepo
└── pnpm-workspace.yaml # если используем pnpm Почему удалённый кеш критичен для CI?
Локальный кеш работает только на одной машине. Для команды и CI нужен remote cache. Vercel Remote Cache — бесплатно для опенсорса, платно для приватных. Self-hosted вариант через turborepo-remote-cache:
# docker-compose.yml для remote cache сервера
services:
turbo-cache:
image: ducktors/turborepo-remote-cache:latest
ports:
- "3000:3000"
environment:
TURBO_TOKEN: "your-secret-token"
STORAGE_PROVIDER: "s3"
S3_BUCKET: "turbo-cache-bucket"
AWS_ACCESS_KEY_ID: "${AWS_ACCESS_KEY_ID}"
AWS_SECRET_ACCESS_KEY: "${AWS_SECRET_ACCESS_KEY}"
Таблица 1: Сравнение кеширования: локальный vs удалённый
| Критерий | Локальный кеш | Удалённый кеш (S3) |
|---|---|---|
| Скорость | Быстро (диск) | Быстро (сеть) |
| Доступность | Только на машине | Вся команда + CI |
| Экономия времени | 50% | 70% |
| Настройка | Автоматически | Docker + S3 |
Таблица 2: Сравнение инструментов monorepo
| Инструмент | Параллелизация | Кеширование | Сложность настройки |
|---|---|---|---|
| npm workspaces | Нет | Нет | Низкая |
| Turborepo | Да | Да | Средняя |
| Nx | Да | Да | Высокая |
Конфигурация turbo.json
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": [".env"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"inputs": ["src/**", "package.json", "tsconfig.json"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
"env": ["NODE_ENV", "API_URL"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"inputs": ["src/**", "*.ts", "*.tsx", ".eslintrc*"],
"outputs": []
},
"typecheck": {
"dependsOn": ["^build"],
"inputs": ["src/**", "tsconfig.json"],
"outputs": []
},
"test": {
"dependsOn": ["^build"],
"inputs": ["src/**", "test/**", "vitest.config.*"],
"outputs": ["coverage/**"],
"env": ["TEST_DATABASE_URL"]
},
"test:e2e": {
"dependsOn": ["build"],
"inputs": ["e2e/**", "playwright.config.*"],
"outputs": ["test-results/**"],
"cache": false
},
"db:generate": {
"cache": false,
"inputs": ["prisma/schema.prisma"]
}
}
} Настройка пакетов и общие конфиги
// packages/ui/package.json
{
"name": "@acme/ui",
"version": "0.0.0",
"private": true,
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./styles": "./dist/styles.css"
},
"scripts": {
"build": "tsup src/index.ts --format esm --dts",
"dev": "tsup src/index.ts --format esm --dts --watch"
},
"devDependencies": {
"@acme/eslint-config": "*",
"@acme/typescript-config": "*",
"tsup": "^8.0.0"
},
"peerDependencies": {
"react": "^18.0.0"
}
} Как настроить CI с Turborepo?
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
ci:
runs-on: ubuntu-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: pnpm/action-setup@v3
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm turbo lint typecheck test --filter=...[HEAD^1]
- run: pnpm turbo build
Типичные ошибки и их решение
- Не указали
envв pipeline — кеш выдаёт старые значения. - Забыли
persistent: trueдля dev — watcher не запускается. - Circular dependencies — проверяйте граф зависимостей.
- Отсутствие
fetch-depth: 2в CI — фильтр...[HEAD^1]не работает. - Неправильная настройка удалённого кеша — убедитесь, что
TURBO_TOKENиTURBO_TEAMустановлены.
Процесс настройки Turborepo под ключ
Мы проводим полный цикл: аудит текущей архитектуры, проектирование структуры monorepo, настройка turbo.json, создание общих пакетов (TypeScript, ESLint, Tailwind), развёртывание удалённого кеша на S3, интеграция с CI/CD, написание документации и обучение команды. Результат: сборка в 3–5 раз быстрее, кеширование на CI, единая кодовая база. Экономия времени разработки может достигать 80%. Получите консультацию нашего инженера — мы поможем ускорить ваш CI.
Сроки и экономия
Настройка с нуля для проекта с 5–8 пакетами занимает два-три дня. Перенос существующего проекта в monorepo — около недели. Стоимость рассчитывается индивидуально в зависимости от сложности и количества пакетов. Гарантируем поддержку после запуска. Наш опыт — более 50 monorepo-проектов, семь лет в веб-разработке.
Как Turborepo ускоряет сборку?
Параллелизация задач на основе графа зависимостей позволяет запускать независимые задачи одновременно. Кеширование результатов (локальное и удалённое) пропускает пересборку неизменившихся пакетов. Встроенный фильтр --filter запускает задачи только для затронутых изменением пакетов и их зависимостей. По данным официальной документации Turborepo, параллелизация сокращает время сборки до 5 раз.
Почему remote cache обязателен для команды?
Без удалённого кеша каждый разработчик и CI-сервер собирают одни и те же пакеты заново. Self-hosted remote cache на S3 или MinIO синхронизирует кеш между всеми участниками. Настройка занимает пару часов, но экономит часы сборки ежедневно. Для коммерческих проектов мы рекомендуем self-hosted решение — оно даёт полный контроль и не зависит от внешнего провайдера.
Заключение
Turborepo — эффективный инструмент для ускорения CI и упрощения работы с monorepo. Правильная настройка с удалённым кешем и грамотным pipeline приносит ощутимую экономию времени и ресурсов. Мы готовы помочь с внедрением — свяжитесь для консультации.







