PurpleSchool — курсы программирования онлайн
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • AI для кодаНовое
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    Монорепозиторий на Turborepo: как организовать фронт и бэк в одном репо

    Монорепозиторий на Turborepo: как организовать фронт и бэк в одном репо

    Аватар автора Монорепозиторий на Turborepo: как организовать фронт и бэк в одном репо

    Антон Ларичев

    Иконка календаря10 апреля 2026
    typescriptreactnodejsmiddleИконка уровня middle
    Картинка поста Монорепозиторий на Turborepo: как организовать фронт и бэк в одном репо

    Введение

    Монорепозиторий на Turborepo позволяет объединить фронтенд и бэкенд в одном репозитории, сохраняя при этом четкое разделение ответственности и высокую скорость сборки. Если вы работаете с React и NestJS, такая организация проекта ускоряет разработку за счет переиспользования типов, утилит и конфигураций между приложениями.

    В этой статье разберем, как организовать фронтенд и бэкенд в одном репо с помощью Turborepo, настроить workspace, общие пакеты и pipeline задач. Покажем реальную структуру проекта, которую можно сразу применить в продакшне.

    Почему монорепозиторий на Turborepo, а не мультирепо

    Когда фронтенд и бэкенд живут в разных репозиториях, появляются типичные проблемы: дублирование типов, рассинхронизация API-контрактов, сложность локальной разработки. Монорепозиторий решает их, но без правильного инструмента превращается в медленный монолит.

    Turborepo решает проблему производительности через:

    • Инкрементальные сборки — пересобираются только измененные пакеты
    • Кэширование результатов — повторные сборки завершаются мгновенно
    • Параллельное выполнение — независимые задачи запускаются одновременно
    • Pipeline задач — turbo.json описывает зависимости между задачами

    В отличие от Nx, Turborepo не требует плагинов и сложной конфигурации. Вы описываете задачи в turbo.json и продолжаете использовать привычные скрипты package.json.

    Структура монорепозитория: apps и packages

    Стандартная структура Turborepo проекта разделяет код на два каталога:

    monorepo/
    ├── apps/
    │   ├── web/              # Next.js фронтенд
    │   └── api/              # NestJS бэкенд
    ├── packages/
    │   ├── shared-types/     # Общие TypeScript типы
    │   ├── ui/               # UI-компоненты (React)
    │   ├── config-eslint/    # Общая конфигурация ESLint
    │   └── config-typescript/# Общий tsconfig
    ├── turbo.json
    ├── package.json
    ├── pnpm-workspace.yaml
    └── .gitignore
    

    Каталог apps/ содержит приложения — это то, что деплоится. Каталог packages/ содержит общие библиотеки, которые используются приложениями как зависимости.

    Как настроить Turborepo с pnpm с нуля

    Начнем с инициализации проекта. Используем pnpm как пакетный менеджер — он лучше всего работает с workspace:

    # Создаем проект
    npx create-turbo@latest my-monorepo
    cd my-monorepo
    

    Если настраиваете вручную, создайте корневой package.json:

    {
      "name": "my-monorepo",
      "private": true,
      "scripts": {
        "build": "turbo run build",
        "dev": "turbo run dev",
        "lint": "turbo run lint",
        "test": "turbo run test"
      },
      "devDependencies": {
        "turbo": "^2.0.0"
      },
      "packageManager": "pnpm@9.0.0"
    }
    

    И pnpm-workspace.yaml:

    packages:
      - "apps/*"
      - "packages/*"
    

    Настройка turbo.json для фронтенда и бэкенда

    Файл turbo.json описывает pipeline — какие задачи запускать и как они зависят друг от друга:

    {
      "$schema": "https://turbo.build/schema.json",
      "tasks": {
        "build": {
          "dependsOn": ["^build"],
          "outputs": ["dist/**", ".next/**"]
        },
        "dev": {
          "cache": false,
          "persistent": true
        },
        "lint": {
          "dependsOn": ["^build"]
        },
        "test": {
          "dependsOn": ["build"]
        }
      }
    }
    

    Символ ^ в dependsOn означает: сначала собери зависимости пакета, потом сам пакет. Это гарантирует, что shared-types соберется раньше, чем web или api.

    Общие типы между фронтендом и бэкендом

    Главное преимущество монорепозитория — единый источник правды для типов. Создадим пакет shared-types:

    // packages/shared-types/src/index.ts
    export interface User {
      id: string;
      email: string;
      name: string;
      role: 'admin' | 'user';
      createdAt: string;
    }
    
    export interface ApiResponse<T> {
      data: T;
      message: string;
      statusCode: number;
    }
    
    export interface PaginatedResponse<T> extends ApiResponse<T[]> {
      total: number;
      page: number;
      limit: number;
    }
    

    Теперь и фронтенд, и бэкенд используют одни и те же интерфейсы:

    // apps/api/src/users/users.controller.ts
    import { User, ApiResponse } from '@monorepo/shared-types';
    
    @Controller('users')
    export class UsersController {
      @Get(':id')
      async getUser(@Param('id') id: string): Promise<ApiResponse<User>> {
        const user = await this.usersService.findById(id);
        return { data: user, message: 'OK', statusCode: 200 };
      }
    }
    
    // apps/web/src/api/users.ts
    import { User, ApiResponse } from '@monorepo/shared-types';
    
    export async function fetchUser(id: string): Promise<User> {
      const res = await fetch(`/api/users/${id}`);
      const json: ApiResponse<User> = await res.json();
      return json.data;
    }
    

    Если кто-то изменит интерфейс User, TypeScript сразу покажет ошибки и во фронтенде, и в бэкенде. Никакой рассинхронизации.

    Локальная разработка: запуск фронта и бэка одной командой

    Одна из самых удобных возможностей Turborepo — запуск всех приложений одной командой:

    # Запустить все приложения в dev-режиме
    pnpm dev
    
    # Запустить только фронтенд
    pnpm dev --filter=web
    
    # Запустить фронтенд и его зависимости
    pnpm dev --filter=web...
    

    Флаг --filter позволяет работать с конкретным приложением. Три точки (...) означают: запусти пакет и все его зависимости. Это удобно, когда вы меняете общие типы и хотите видеть результат во фронтенде.

    Частые ошибки при организации монорепозитория

    Слишком много общих пакетов. Не выносите в отдельный пакет код, который использует только одно приложение. Начните с shared-types и добавляйте пакеты по мере необходимости.

    Циклические зависимости. Если пакет A зависит от B, а B от A, Turborepo не сможет определить порядок сборки. Решение — вынести общий код в третий пакет.

    Отсутствие outputs в turbo.json. Без указания outputs кэширование не работает. Всегда прописывайте, какие файлы создает задача: dist/** для библиотек, .next/** для Next.js.

    Тяжелый корневой package.json. Не устанавливайте зависимости приложений в корень. Каждое приложение должно объявлять свои зависимости в собственном package.json.

    Заключение

    Монорепозиторий на Turborepo — это практичный способ организовать фронтенд и бэкенд в одном репозитории без потери скорости сборки. Вы получаете единые типы, удобную локальную разработку и автоматическое кэширование. Начните с простой структуры — apps/ для приложений и packages/ для общего кода — и расширяйте по мере роста проекта. Turborepo не навязывает архитектуру, а ускоряет ту, которую вы выбрали сами.

    Иконка глаза882

    Комментарии

    0

    Постройте личный план изучения Основы React, React Router и Redux Toolkit до уровня Middle — бесплатно!

    Основы React, React Router и Redux Toolkit — часть карты развития Frontend, Mobile

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Zustand

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Next.js - с нуля

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.7
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Feature-Sliced Design

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.5
    3 999 ₽ 6 990 ₽
    Подробнее

    Похожие статьи

    Картинка поста Тестирование React-компонентов с React Testing Library
    Иконка аватараАнтон
    Иконка календаря07 июля 2026
    reacttestingreact-testing-library+ 2middleИконка уровня middle

    Тестирование React-компонентов с React Testing Library

    React Testing Library — инструмент для тестирования React-компонентов через поведение пользователя, а не детали реализации. Примеры, паттерны, частые ошибки.

    Иконка чипа0
    Иконка глаза116
    Иконка комментариев0
    Картинка поста Микрофронтенды и Module Federation: подходы и реализация
    Иконка аватараАнтон
    Иконка календаря06 июля 2026
    микрофронтендыmodule-federationwebpack+ 2seniorИконка уровня senior

    Микрофронтенды и Module Federation: подходы и реализация

    Микрофронтенды с Module Federation: как разбить монолитный фронтенд на независимые части, которые деплоятся и разрабатываются отдельно.

    Иконка чипа0
    Иконка глаза135
    Иконка комментариев0
    Картинка поста Clean Architecture: чистая архитектура для веб-разработки
    Иконка аватараАнтон
    Иконка календаря02 июля 2026
    архитектураclean architecturetypescript+ 3middleИконка уровня middle

    Clean Architecture: чистая архитектура для веб-разработки

    Clean Architecture разделяет код на независимые слои: бизнес-логика не зависит от фреймворков, БД и внешних сервисов. Разбираем на примерах TypeScript.

    Иконка чипа0
    Иконка глаза173
    Иконка комментариев0
    Иконка чипа0