Что такое Lerna и зачем он нужен?

Когда вы работаете над большим JavaScript-проектом, который состоит из нескольких взаимосвязанных пакетов (например, библиотек, компонентов интерфейса, CLI-утилит и т.п.), организация и управление зависимостями может быстро превратиться в хаос. Вот здесь и вступает в игру Lerna — это мощный инструмент, который упрощает управление многопакетными репозиториями. Он помогает синхронизировать версии, управлять зависимостями между пакетами и автоматизировать публикацию.
Lerna особенно полезен в экосистемах, где проект разделён на модули: например, в монорепозиториях, которые содержат и фронтенд, и бекенд, и общее ядро. Такие многопакетные проекты с Lerna становятся проще в поддержке и масштабировании. Это один из самых популярных инструментов для управления пакетами JavaScript в подобных случаях.
Шаг 1: Установка и инициализация проекта с Lerna
Для начала убедитесь, что у вас установлен Node.js и npm. Затем глобально установите Lerna с помощью команды:
```
npm install -g lerna
```
Создайте новую папку под ваш проект и инициализируйте Lerna:
```
mkdir my-monorepo && cd my-monorepo
lerna init
```
Эта команда создаст базовую структуру проекта: директорию `packages/`, где будут лежать все ваши модули, и файл `lerna.json`, в котором указывается конфигурация. Здесь же можно настроить, будет ли проект использовать фиксированные версии для всех пакетов или независимые — это влияет на то, как Lerna будет управлять версиями при публикации.
Совет для новичков
Если вы только начинаете использовать Lerna для многопакетных проектов, начните с режима фиксированных версий (`version: "0.0.0"` в `lerna.json`). Это упростит управление зависимостями, особенно если ваши модули тесно связаны между собой.
Шаг 2: Добавление пакетов в структуру проекта
Теперь можно создавать пакеты. Каждый из них — это по сути отдельный npm-модуль. Например:
```
cd packages
mkdir core utils ui
cd core && npm init -y
```
Повторите `npm init` для каждого пакета. В итоге у вас получится три модуля: `core`, `utils` и `ui`, каждый со своим `package.json`. Теперь можно связать их зависимости. Например, если `ui` использует функции из `utils`, добавьте в `ui/package.json` строку:
```json
"dependencies": {
"utils": "0.0.0"
}
```
Затем выполните:
```
lerna bootstrap
```
Эта команда установит все внешние зависимости и создаст символические ссылки между локальными пакетами. Это ключевой момент: Lerna в JavaScript-проектах позволяет избежать публикации пакетов в npm до того, как они будут полностью готовы. Всё работает локально, как единое целое.
Шаг 3: Работа с зависимостями и версиями

Lerna предлагает удобные команды для работы с зависимостями. Например, чтобы добавить lodash только в пакет `utils`, используйте:
```
lerna add lodash --scope=utils
```
Чтобы добавить локальную зависимость, например, `core` в `ui`, достаточно:
```
lerna add core --scope=ui
```
Когда вы вносите изменения в один из пакетов, Lerna может автоматически определить, какие ещё модули затронуты, и обновить зависимости. Это особенно полезно при подготовке к публикации. Команда `lerna publish` поможет опубликовать только изменённые пакеты, с обновлёнными версиями и тегами в git.
Предупреждение об ошибках
Одна из частых ошибок — забыть про `lerna bootstrap` после добавления новых пакетов или зависимостей. Это приводит к ошибкам `MODULE_NOT_FOUND`. Также старайтесь избегать циклических зависимостей между модулями — Lerna не сможет корректно связать их и выдаст ошибку.
Шаг 4: Интеграция с Yarn Workspaces
Хотя Lerna сама по себе мощный инструмент, она отлично сочетается с Yarn Workspaces. Это особенно актуально, если вы хотите ускорить установку зависимостей и избежать дублирования. Для этого в `lerna.json` добавьте:
```json
"useWorkspaces": true
```
И в `package.json` в корне проекта:
```json
"private": true,
"workspaces": ["packages/*"]
```
Теперь при запуске `lerna bootstrap` Lerna будет использовать Yarn Workspaces для установки зависимостей, что значительно ускорит процесс и сделает структуру проекта ещё чище.
Практический кейс: библиотека компонентов UI
Один из реальных кейсов использования — разработка библиотеки компонентов интерфейса. Допустим, у вас есть следующие пакеты:
- `@company/button` — кнопка
- `@company/input` — поле ввода
- `@company/theme` — темы и стилизация
Каждый компонент — это отдельный npm-пакет. С помощью Lerna вы можете разрабатывать их изолированно, но при этом иметь единый процесс сборки, тестирования и публикации. Например, при изменении темы вы можете автоматически обновить версии всех компонентов, которые её используют.
Это особенно удобно в больших командах, где каждый разработчик отвечает за свой компонент. Управление проектами с Lerna даёт централизованный контроль, но при этом сохраняет гибкость.
Кейс из мира CLI-инструментов
Другой пример — CLI-инструмент, который состоит из нескольких подмодулей, таких как парсер аргументов, обработчик команд и генератор шаблонов. Всё это можно оформить в виде отдельных пакетов:
- `@cli/parser`
- `@cli/commands`
- `@cli/templates`
С Lerna вы можете разрабатывать каждый из этих модулей независимо, но собирать их в единый CLI-инструмент. Это ускоряет разработку, облегчает тестирование и позволяет переиспользовать модули в других проектах.
Вывод: стоит ли использовать Lerna?
Если вы занимаетесь разработкой сложных JavaScript-решений, которые состоят из множества взаимосвязанных модулей, использование Lerna — это не просто удобно, а зачастую необходимо. Это один из лучших инструментов для управления пакетами JavaScript в монорепозиториях. Благодаря автоматизации, управлению зависимостями и интеграции с Yarn Workspaces, вы тратите меньше времени на рутину и больше — на реальную разработку.
Многопакетные проекты с Lerna становятся масштабируемыми, прозрачными и удобными для команды любого размера. Главное — правильно организовать структуру и не забывать про лучшие практики. С Lerna в JavaScript вы сможете не просто поддерживать порядок в коде, но и ускорить выход новых версий ваших продуктов.



