Монорепозиторий — удобный формат для команды, которая развивает несколько пакетов одновременно. Lerna помогает связать эти пакеты, упростить установку зависимостей и автоматизировать релизы. В статье разберу, что делает Lerna полезным инструментом, как правильно его настроить и какие подводные камни стоит предусмотреть.
Кратко о том, зачем нужен Lerna
Lerna обеспечивает управление набором пакетов внутри одного репозитория. Он облегчает запуск скриптов по всем пакетам, оптимизирует установку общих зависимостей и помогает управлять версиями при публикации.
Главная идея — избежать дублирования и упростить рабочий цикл: вы можете менять несколько пакетов в одном коммите, запускать тесты централизованно и публиковать только то, что действительно изменилось.
Основные возможности
Lerna содержит набор команд, которые решают типовые задачи монорепозитория. Среди них bootstrap для связывания локальных пакетов, run для выполнения скриптов и publish для автоматического повышения версий и публикации в npm.
Отдельная опция — hoist, она поднимает общие зависимости в корень репозитория. Это экономит дисковое пространство и ускоряет установку, но требует внимания к совместимости версий.
- bootstrap — связывает локальные зависимости и устанавливает внешние;
- run / exec — запускает команды во множестве пакетов;
- publish — автоматизирует версионирование и публикацию;
- changed — определяет пакеты, затронутые последними коммитами.
Когда Lerna — хороший выбор
Если у вас несколько связанных пакетов и вы хотите управлять ими централизованно, Lerna часто оказывается проще, чем полностью ручной подход. Особенно это касается библиотек и SDK, где пакеты тесно связаны между собой.
При малом и среднем числе пакетов Lerna позволяет быстро организовать рабочий процесс и обеспечить единообразие скриптов. Однако при очень большом количестве пакетов появляются преимущества инструментов с продвинутым кэшированием сборок.
Кому стоит посмотреть в сторону альтернатив
Если критичны быстрые инкрементальные сборки и сложные зависимости между проектами, имеет смысл рассмотреть Nx или Turborepo. Эти системы содержат встроенное кэширование и граф задач, что экономит время CI.
Также в экосистеме развиваются workspace-подходы менеджеров пакетов — Yarn и pnpm — они отлично работают совместно с Lerna или сами по себе решают часть задач по управлению зависимостями.
Небольшая сравнительная таблица
| Инструмент | Управление зависимостями | Кэш сборок | Лучше для |
|---|---|---|---|
| Lerna | Работает с npm/Yarn/pnpm; поддерживает hoist | Нет встроенного | Управление пакетами и релизами |
| Yarn Workspaces | Интегрированное, простая конфигурация | Нет | Упрощённая установка зависимостей |
| pnpm Workspaces | Эффективное хранение пакетов, жёсткая изоляция | Частично через кеш менеджера | Проекты с большим количеством пакетов |
| Nx / Turborepo | Работают с workspaces | Да, продвинутое | Большие монорепозитории с CI-оптимизацией |
Установка и базовая настройка
Начать просто: в корне репозитория создайте package.json и выполните инициализацию Lerna. Можно установить Lerna глобально или как dev-зависимость — выбирайте подход, удобный команде.
Типичный набор шагов выглядит так: инициализация npm, установка Lerna, создание папки packages и запуск lerna init. В lerna.json укажите npmClient и режим версии — фиксированную или независимую.
- npm init -y
- npm i -D lerna
- npx lerna init
- создайте структуру packages/* с package.json в каждом пакете
Пример минимального lerna.json:
{
"packages": ["packages/*"],
"version": "independent",
"npmClient": "pnpm"
}
Практический пример структуры
Обычная структура монорепозитория выглядит предельно ясно: корень с конфигами и папка packages, в которой лежат отдельные модули. Каждый модуль — это полноценный npm-пакет со своим package.json.
- /package.json — общие скрипты и dev-зависимости;
- /lerna.json — конфигурация Lerna;
- /packages/ui — компонентная библиотека;
- /packages/core — бизнес-логика;
- /packages/app — приложение, собираемое из внутренних пакетов.
Такое расположение упрощает локальное тестирование: при изменении core и сборке app Lerna автоматически свяжет локальные версии вместо загрузки из npm.
Советы по настройке зависимостей и hoisting
Hoisting экономит место и ускоряет npm install, но поднимает риск конфликтов версий. Если пакеты требуют разных версий одной библиотеки, hoist может ломать резолвинг модулей.
Практика показывает: включайте hoist для проектов со стабильной зависимостью, а в сложных случаях комбинируйте его с workspaces менеджера пакетов и точной фиксацией версий.
Автоматизация версий и публикаций
Lerna умеет вычислять, какие пакеты изменились, и повышать версии только для них. Это экономит время и уменьшает число публикаций.
Для управления процессом релизов удобно использовать схему conventional commits. Она даёт предсказуемые changelog и позволяет автоматизировать шаги в CI.
Типичные ошибки и как их избежать
Частая ошибка — смешение подходов: попытки полностью довериться Lerna для всех задач, не учитывая преимущества workspaces и кэша. Это ведёт к неэффективным сборкам и запутанным конфликтам зависимостей.
Другой источник проблем — неконсистентные версии зависимостей в пакетах. Рекомендую централизовать версии для ключевых библиотек и проверять их скриптами.
Опыт из практики
В одном из проектов мы использовали Lerna вместе с pnpm workspaces. Сначала всё шло гладко: разработчики могли одновременно работать над библиотеками и приложением. Публикации сократились, потому что Lerna публиковала только пакет с изменениями.
Проблемы возникли, когда начали экспериментировать с hoist: пара пакетов требовала разных minor-версий одной библиотеки, и разрешение импортов ломалось на CI. Решение — ограничить hoisting или унифицировать версии.
Переход на современные инструменты и интеграция с CI
Если проект растёт, имеет смысл добавить систему кэширования сборок и граф задач. Nx и Turborepo интегрируются с workspaces и дают выигрыш по времени в CI. Lerna при этом остаётся полезным для управления пакетами и публикаций.
В CI настройте кэш node_modules и кэш сборки. Также используйте команды вроде lerna changed, чтобы запускать тесты и сборки только для затронутых пакетов — это экономит ресурсы и ускоряет конвейер.
Когда мигрировать с Lerna
Если чашка сборок и трафик CI выросли до точки, где сборки занимают большую часть времени, подумайте о миграции. Lerna по-прежнему хорош для релизов, но тушение времени билда решают другие инструменты.
Миграция обычно включает перенос управления зависимостями в workspaces выбранного менеджера, добавление кэша задач и постепенное внедрение графа зависимостей. Делать это осторожно — пакет за пакетом.
Краткий чеклист перед внедрением
Перед тем как заводить Lerna в проект, проверьте несколько ключевых пунктов. Это поможет избежать типичных ошибок и сделает интеграцию предсказуемой.
- Определите число и тип пакетов — библиотеки или приложения;
- Решите стратегию версии: фиксированная или независимая;
- Выберите менеджер пакетов и подумайте о workspaces;
- Настройте CI с кэшем и ограничением областей сборки;
- Документируйте скрипты и порядок релизов для команды.
Lerna остаётся практичным инструментом для тех, кто ценит простоту управления пакетами и автоматизацию выпуска. При разумной конфигурации он экономит время разработчиков и уменьшает количество рутины вокруг версий. Важно учитывать масштаб проекта и сочетать Lerna с workspaces и инструментами кэширования там, где это даёт реальную выгоду.

