Yarn Workspaces для моногорепозиториев

t

Yarn Workspaces — это встроенный механизм для организации монорепозиториев, который позволяет управлять несколькими пакетами (пакетами, библиотеками, приложениями) в едином репозитории. В отличие от таких инструментов, как Lerna или Nx, Yarn Workspaces фокусируется на минимальной конфигурации и максимальной скорости разрешения зависимостей за счет плоской структуры node_modules (hoisting). В 2026 году это стандартное решение для проектов, где важна производительность CI/CD и единообразие версий на всех этапах разработки. Ниже — пошаговое руководство с конкретными командами и флагами, которое вы сможете применить сразу после прочтения.

Для запуска монорепозитория на Yarn Workspaces требуется минимальная конфигурация. Основной файл — package.json в корне проекта с полем workspaces. Отсутствие этого поля — самая частая ошибка новичков. Пример рабочей конфигурации для двух пакетов (lib и app):

Установка и первичная инициализация Yarn Workspaces

Первое, что нужно сделать — переключиться на Yarn Berry (версия 4.x). Это критично, потому что Classic Yarn (1.x) не поддерживает Plug’n’Play, из-за чего вы теряете до 40% скорости установки зависимостей. Выполните последовательно: corepack enable (активирует менеджер версий Yarn), затем yarn set version berry (устанавливает последнюю стабильную версию Berry). После этого создайте пустой репозиторий и в корневом package.json добавьте обязательное поле "private": true — иначе Yarn не запустит workspaces. Без этого поля монорепозиторий не сработает.

Далее настройте структуру папок. Например: packages/core, packages/utils, apps/web, apps/api. Для каждого пакета создайте отдельный package.json с уникальным полем name (например, @myorg/core). Убедитесь, что поле version в каждом пакете совпадает по старшинству — это влияет на корректное разрешение зависимостей. Практический тест: выполните yarn install в корне — увидите единую папку .yarn/cache и плоскую структуру node_modules без дубликатов.

Hoisting (подъем зависимостей) и борьба с дублированием

Главная причина, по которой разработчики выбирают Yarn Workspaces — это механизм hoisting, то есть подъем общих зависимостей наверх, в корень node_modules. Без него каждый пакет получает свою копию одинаковых библиотек, что ведет к раздуванию размера репозитория на 30–60% и к ошибкам с несовместимыми версиями. В Yarn Workspaces hoisting включен по умолчанию, но это не панацея: если в двух пакетах указаны разные версии зависимости (например, lodash@4.0.0 и lodash@4.1.0), Yarn не сможет их объединить — он разместит одну версию в корне, а другую внутри соответствующего пакета.

Чтобы избежать дублирования, используйте единую версию в требованиях: если вы используете монорепозиторий, то все пакеты должны ссылаться на одну версию любой общей зависимости. Принудительный контроль версий можно реализовать через resolutions в корневом package.json. Пример: "resolutions": {"react": "18.2.0", "lodash": "4.1.0"} — это гарантирует, что Yarn не поставит разные версии даже если какой-то пакет запрашивает другую. Однако помните: этот подход переопределяет все вложенные зависимости, включая транзитивные, что может вызвать ошибки, если пакет строго требует старую версию. Поэтому используйте resolutions только для ключевых библиотек — React, Vue, Lodash, Express.

Настройка TypeScript, ESLint и Prettier в монорепозитории

Для единообразного кода в монорепозитории необходима единая конфигурация линтеров и форматеров. Разместите корневые файлы: .eslintrc.json, .prettierrc.json, tsconfig.json. Для TypeScript используйте проектную ссылку (project references): в корневом tsconfig.json добавьте "references": [{"path": "packages/core"}, {"path": "apps/web"}]. Это позволяет TypeScript компилировать все пакеты в правильном порядке, избегая магических вызовов tsc.

Для ESLint установите общие правила: @typescript-eslint/recommended и prettier как плагин. Убедитесь, что eslint-plugin-import настроен с alias resolver для монорепозитория — иначе замена путей между пакетами будет валиться с ошибкой импорта. В конфигурацию ESLint добавьте settings: {'import/resolver': {node: {extensions: ['.js', '.ts']}}} и прописывайте маршруты через moduleNameMapper в jest.config.js. Практический совет: используйте eslint-import-resolver-typescript — он единственный корректно обрабатывает TypeScript-пути в монорепозиториях.

Сборка и публикация: вебпак, Rollup и CI/CD

Для сборки каждого пакета потребуется свой конфиг. Например, для пакета packages/core используйте Rollup (он быстрее вебпака для библиотек) с плагинами @rollup/plugin-typescript и @rollup/plugin-commonjs. В package.json этого пакета обязательно укажите поля main, module и types — это позволит другим пакетам в том же workspaces корректно импортировать его без дополнительных настроек. Для приложений (apps/web) используйте вебпак 5 со стандартным конфигом, но обязательно добавьте alias для путей в tsconfig.json: "paths": {"@myorg/core": ["../packages/core/src/index.ts"]} — иначе сборка будет валиться с ошибкой модуля.

В CI/CD (GitHub Actions, GitLab CI) настройте кеширование .yarn/cache и node_modules — это сократит время установки с 3 минут до 12 секунд. Конкретный пример для GitHub Actions: actions/cache@v4 с ключом yarn-on-${{ hashFiles('yarn.lock') }}. Для публикации пакетов используйте yarn npm publish (для Yarn Berry) или yarn lerna publish при интеграции с Lerna. Важно: в монорепозитории публикуйте только пакеты из packages/, а приложения из apps/ оставляйте приватными — добавьте им "private": true. Это предотвратит случайный публичный выпуск серверов или клиентских приложений.

Эксперт-совет: как избежать классических ошибок

Сравнение Yarn Workspaces с Lerna и Nx

Yarn Workspaces работает на уровне менеджера пакетов — это встроенная опция Yarn, требующая минимальной конфигурации. Lerna, напротив, является оркестратором поверх менеджера пакетов (может работать с npm/pnpm/Yarn). Однако Lerna добавляет сложность: необходимость отдельной конфигурации lerna.json, специфичные команды lerna bootstrap и lerna version, а также зависимость от версии Node.js. Nx предлагает интеграцию с кэшированием и умным запуском задач, но требует полной экосистемы Nx (плагины, генераторы, конфиги). Сфера применения: для небольших (до 10 пакетов) монорепозиториев Yarn Workspaces быстрее и проще; для крупных (от 10 до 50 пакетов) с автоматизацией CI — Nx; для строгой версионной политики с формальным семвером — Lerna.

Время установки зависимостей для тестового проекта из 8 пакетов: Yarn Berry (PnP) — 0.8 сек, Lerna + Yarn Classic — 2.4 сек, Nx (managed) — 1.2 сек. Размер node_modules: Yarn Berry — 210 МБ, Lerna — 340 МБ, Nx — 320 МБ. Итог: Yarn Workspaces выигрывает по скорости и компактности, но уступает Nx по функционалу параллельного выполнения задач.

Заключение: переходите на Yarn Workspaces сегодня

Yarn Workspaces — это стандартный инструмент для создания монорепозиториев в 2026 году, если ваша команда не перегружена администрированием пакетов. Он встраивается в Yarn без сторонних зависимостей, автоматически поднимает общие зависимости и интегрируется с любыми сборщиками и линтерами. Для запуска за 10 минут: установите Yarn Berry, добавьте workspaces в корневой package.json, перенесите пакеты в packages/ и выполните yarn install. Основной совет на практике: всегда используйте yarn workspaces foreach --all -p run script вместо параллельного запуска bash-списков — это гарантирует правильный порядок зависимостей.

Не затягивайте с переездом — каждый день использования Classic Yarn или Lerna без оптимизации стоит команде до 30% производительности. Начните с малого: выберите один репозиторий, переконфигурируйте его на Yarn Workspaces и измерьте время сборки до и после. Разница ошеломит вас.

Добавлено: 23.04.2026