Монорепозиторий с TypeScript: организация кода для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Монорепозиторий с TypeScript: организация кода для начинающих

Разработка современных приложений на TypeScript часто требует управления несколькими взаимосвязанными пакетами (например, библиотекой компонентов, бэкенд-сервисом и утилитами). Вместо того чтобы хранить каждый пакет в отдельном репозитории (мультирепозиторий), многие команды выбирают монорепозиторий — единый репозиторий, содержащий все проекты. В этой статье мы разберем, как организовать монорепозиторий с TypeScript, даже если вы новичок.

Что такое монорепозиторий и зачем он нужен?

Монорепозиторий (monorepo) — это подход, при котором код нескольких проектов (пакетов, модулей) хранится в одном репозитории. Это не означает, что все проекты сливаются в одну кучу: они остаются логически разделенными, но находятся под одной крышей.

Преимущества для проектов на TypeScript:

  • Единая версия зависимостей. Вы избегаете ситуации, когда в разных пакетах используются разные версии TypeScript или одной и той же библиотеки.
  • Простой рефакторинг. Изменение общего интерфейса или типа в одном месте сразу обновляется во всех зависимых пакетах.
  • Упрощенная публикация. Инструменты для монорепозитория (например, Lerna или Nx) помогают автоматически публиковать только измененные пакеты.
  • Общие настройки. Вы можете иметь один tsconfig.json для всех пакетов, переопределяя его при необходимости.

Инструменты для создания монорепозитория

Для работы с монорепозиторием в TypeScript существует несколько популярных инструментов:

  • npm Workspaces — встроенная возможность npm, начиная с версии 7. Простая и эффективная.
  • Yarn Workspaces — аналогичная функция в пакетном менеджере Yarn.
  • Lerna — классический инструмент, который часто используется поверх npm или Yarn Workspaces.
  • Nx — мощная система для монорепозиториев с расширенными возможностями кэширования и генерации кода.
  • Turborepo — современный инструмент от Vercel, ориентированный на скорость и простоту.

В этом руководстве мы будем использовать npm Workspaces, так как это самый простой способ, не требующий установки дополнительных глобальных инструментов.

Пошаговая настройка монорепозитория с TypeScript

1. Создание корневой структуры

Начните с создания корневой папки вашего монорепозитория и инициализации package.json:

mkdir my-monorepo
cd my-monorepo
npm init -y

Теперь отредактируйте корневой package.json, добавив поле workspaces. Это укажет npm, где искать ваши пакеты:

{
  "name": "my-monorepo",
  "private": true,
  "workspaces": [
    "packages/*"
  ]
}

Флаг "private": true предотвращает случайную публикацию корневого пакета в npm.

2. Создание пакетов

Создайте структуру папок для ваших пакетов. Типичная структура выглядит так:

my-monorepo/
├── packages/
│   ├── utils/          # Общие утилиты
│   ├── ui/             # Библиотека компонентов
│   └── backend/        # Серверное приложение
├── package.json
└── tsconfig.json

Создайте папку packages и внутри нее — папки для каждого пакета. В каждом пакете должен быть свой package.json. Например, для пакета utils:

mkdir -p packages/utils
cd packages/utils
npm init -y

Отредактируйте packages/utils/package.json, добавив имя и, возможно, версию:

{
  "name": "@my-project/utils",
  "version": "1.0.0",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "scripts": {
    "build": "tsc"
  }
}

3. Настройка TypeScript

В корне проекта создайте базовый tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020"],
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "outDir": "./dist",
    "rootDir": "./packages"
  },
  "include": ["packages/**/*"],
  "exclude": ["node_modules", "dist"]
}

Теперь в каждом пакете вы можете создать свой tsconfig.json, который расширяет корневой. Например, для packages/utils/tsconfig.json:

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"]
}

4. Написание кода и создание зависимостей

Создайте простой модуль в packages/utils/src/index.ts:

export function greet(name: string): string {
  return `Hello, ${name}!`;
}

export function add(a: number, b: number): number {
  return a + b;
}

Теперь создайте пакет backend, который будет использовать @my-project/utils. В packages/backend/package.json добавьте зависимость:

{
  "name": "@my-project/backend",
  "version": "1.0.0",
  "scripts": {
    "start": "ts-node src/index.ts"
  },
  "dependencies": {
    "@my-project/utils": "*"
  }
}

Обратите внимание на "*" — это означает, что будет использоваться любая версия пакета из вашего монорепозитория. После редактирования package.json выполните в корне проекта:



                
                

Блоги

Рекомендаций по книгам