Noveo

Наш блог Разработка взаимосвязанных библиотек, серверных и кроссплатформенных приложений с использованием монорепозитория

Разработка взаимосвязанных библиотек, серверных и кроссплатформенных приложений с использованием монорепозитория

Предлагаем вашему вниманию разбор преимуществ и недостатков монорепозиториев от разработчика Noveo Александра:

 

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

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

 

Есть несколько способов это сделать:

  1. копировать-вставить;
  2. общие пакеты (библиотеки);
  3. хранить все в одном месте (монорепозиторий).

 

Первый способ хоть и выглядит самым простым, в действительности создает очень серьезную проблему: все копии какого-либо ресурса поддерживаются вручную без каких-либо вспомогательных инструментов. Это, в свою очередь, на крупном проекте может привести к тому, что количество отдельно поддерживаемых строк кода станет очень большим, из-за чего стоимость каждого изменения будет становиться все дороже.

 

Следующий способ является улучшенной версией первого за счет автоматизированных инструментов по работе с копированием (менеджер пакетов и версий). Т.е. за счет специализированных инструментов каждая отдельно взятая копия общего ресурса может быть в точности переиспользована и при необходимости обновлена.

 

Этот метод в значительной степени превосходит предыдущий, но у него есть свои недостатки. Каждый проект работает с отдельной версией того или иного пакета (библиотеки). И в случае, если какой-либо пакет обновится, придется выполнять ручное обновление этой библиотеки для каждого проекта. Такие действия всегда неудобны в рамках какого-то одного программного продукта, состоящего из множества проектов. А если этого не делать, то отдельные проекты начнут работать с legacy-кодом, а в худшем случае способны привести к антипаттерну проектирования “ад зависимостей” (dependency hell).

 

Потому некоторые разработчики программного обеспечения придумали еще один способ: хранить весь код множества проектов в одном месте. Именно этому направлению и посвящена наша статья.

 

Подход, при котором код всех проектов хранится в одном месте (репозитории), называется монорепозиторием. Монорепозиторий — это стратегия разработки программного обеспечения, когда код множества подпроектов хранится в одном и том же репозитории.

 

Если посмотреть на изображение, то можно увидеть прямую иллюстрацию того, как зависимые друг от друга проекты выглядят в случае монорепозитория (MonoRepo) и множества репозиториев (ManyRepo).

Плюсы и минусы монорепозитория

Плюсы

  • Упрощенное управление зависимостями — так как все зависимости находятся внутри одной кодовой базы.
  • Атомарные коммиты — т.е. возможность создавать неделимые коммиты для всех проектов.
  • Крупномасштабный рефакторинг кода — возможность рефакторить все проекты сразу.
  • Сотрудничество между командами — разные команды могут совместно работать над общими проектами.

Минусы

  • Потеря информации версий — в монорепозитории, как правило, всегда находится только одна версия каждого проекта, без возможности использовать две разные версии для разных проектов.
  • Отсутствие надёжности подпроектов — все проекты доступны всем разработчикам репозитория.
  • Больший объём хранилища — из-за большого количества проектов и размер репозитория может быть значительно больше.

Примеры использования

Google, Facebook, Microsoft, Twitter, Яндекс, Вконтакте используют огромные монорепозитории; крупнейший — у Google, его размер составляет более 80 терабайт.
Известные JavaScript-проекты, разрабатываемые в монорепозиториях:

  • babel/babel
  • facebook/react
  • facebook/react-native
  • angular/angular
  • vuejs/vue
  • nestjs/nest
  • NativeScript/NativeScript
  • ionic-team/ionic-framework
  • webpack/webpack-cli
  • storybooks/storybook

Монорепозитории JavaScript

В JavaScript есть несколько инструментов, которые предоставляют возможность разрабатывать программное обеспечение по стратегии монорепозитория. Разберем некоторые из них.

Lerna

Вот как выглядит главный экран с официального сайта Lerna.

Т.е. Lerna — это инструмент для управления множеством JavaScript-проектов.

 

Вот что Lerna пишет о своем проекте:
Разделение больших баз кода на отдельные пакеты с независимыми версиями чрезвычайно полезно для совместного использования кода. Однако внесение изменений во многие репозитории беспорядочно и сложно отследить, а тестирование в репозиториях очень быстро усложняется.

 

Чтобы решить эти (и многие другие) проблемы, некоторые проекты организуют свои кодовые базы в репозитории с несколькими пакетами (иногда называемые монорепозиториями). Такие проекты, как Babel, React, Angular, Ember, Meteor, Jest и многие другие, разрабатывают все свои пакеты в одном репозитории.

 

Lerna — инструмент, который оптимизирует рабочий процесс по управлению репозиториями с несколькими пакетами с помощью git и npm.
Lerna также может сократить требования к времени и пространству для многочисленных копий пакетов в средах разработки и сборки — обычно это обратная сторона деления проекта на множество отдельных пакетов NPM.

Как выглядит репо «Лерна»?

На самом деле совсем не сложно. Есть файловая структура, которая выглядит так:
Также имеется конфигурационный файл lerna.json, внутри которого задается конфигурация по работе с монорепозиторием.

Также есть возможность создать более расширенную архитектуру, как показано на примере ниже:

Более подробно с документацией Lerna можно ознакомиться по ссылке: https://github.com/lerna/lerna

Nx — умная расширяемая платформа сборки

Главная страница Nx [https://nx.dev/] выглядит следующим образом:

Это, в свою очередь, дает понять, что Nx предоставляет не только инструменты для работы с монорепозиторием, но и крупные практики по разработке.
И одной из ключевых особенностей Nx является наличие генераторов и исполнителей. Генераторы автоматизируют внесение изменений в файловую систему. Они используются для создания / обновления приложений, библиотек, компонентов и многого другого.

Исполнители определяют, как выполнять действие над проектом. Они используются для сборки приложений и библиотек, их тестирования, линтинга и многого другого.

 

NX из коробки имеет поддержку следующих технологий:

  • Angular
  • React
  • NextJS
  • Node
  • Express
  • NestJS
  • Storybook
  • Cypress

В Nx имеются практики построения продвинутой архитектуры нескольких проектов.

Организация кода и соглашения об именах в Nx

Приложения и библиотеки

Приложения настраивают внедрение зависимостей и подключают библиотеки. Они не должны содержать никаких компонентов, сервисов или бизнес-логики.
Библиотеки содержат службы, компоненты, утилиты и т. д. У них есть четко определенный общедоступный API.

 

Обычно рабочее пространство Nx содержит намного больше библиотек, чем приложений, поэтому обратите особое внимание на организацию каталога libs.

Область действия (Где живет библиотека, кому она принадлежит)

 

Хорошее соглашение — помещать библиотеки для конкретных приложений в каталог, соответствующий имени приложения. Это обеспечивает достаточную организацию для приложений малого и среднего размера.
Для более крупных проектов рекомендуется сгруппировать библиотеки по разделам приложений.
Здесь у нас есть:
happynrwlapp / registration / feature-main — библиотека с ограниченной областью видимости, используемая в одном месте.
happynrwlapp / shared / ui — разделяемая библиотека, используемая в одном приложении.
shared / ui — общая библиотека, используемая в приложениях.

 

Также Nx может быть использован и для создания только одного приложения:

Yarn Workspace

Еще одним наиболее простым способом разрабатывать ПО в монорепозитории с использование JavaScript является Yarn workspace — встроенный механизм в менеджер пакетов yarn.
Чтобы начать работать с монорепозиторием, необходимо в файле package.json прописать пути до соответствующих подпроектов.
Затем необходимо создать package.json в этих директориях с необходимыми зависимостями:

И далее при выполнении команды установки зависимостей они будут установлены таким образом, что все проекты монорепозитория будут иметь к ним доступ:

Более подробная документация находится по ссылке https://classic.yarnpkg.com/en/docs/workspaces/.

Специализированное ПО монорепозитория

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

 

Стоит выделить наиболее значимые инструменты, которыми в идеале должен обладать более-менее крупный монорепозиторий:

  • Исполнитель задач (Task runner) — специальный инструмент, с помощью которого возможно запускать разного рода команды для работы с проектами внутри монорепозитория.
  • Обнаружение изменений (Change detection) — с помощью специализированного ПО внутри крупного монорепозитория необходимо постоянно отслеживать производимые изменения, чтобы в дальнейшем при работе с ним определять наиболее эффективные алгоритмы тестирования, сборки и так далее.
  • Упорядочивание задач (Task ordering) — из-за того, что проекты зависят друг от друга, внутри монорепозитория при выполнении команд необходимо определять очередь задач. Без данного инструмента возможна ситуация, что какой-либо проект может быть запущен раньше, чем будет готова его зависимость.
  • Генераторы (Generators) — так как разрабатываемый программный продукт может быть очень большим, то с помощью генераторов возможно автоматизировать часть работы по написанию/рефакторингу программного кода.

Выводы

Подводя итог, можно сказать следующее: монорепозиторий — стратегия разработки ПО, которая предлагает механизмы для взаимосвязанной разработки сразу нескольких проектов. Однако, как и у любого другого подхода в разработке программного обеспечения, у него есть свои преимущества и недостатки. И как следствие, свои сферы применения.

 

Так, например, монорепозиторий может быть очень удобен в разработке фреймворков, что можно понять по статистике opensource-проектов (react, angular).

Также он может найти свое применение и в разработке множества проектов, которые постоянно используют одни и те же данные, где актуальность крайне важна.

 

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

Полезные материалы

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

НазадПредыдущий пост ВпередСледующий пост

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: