Angular с Nx в 2023 году? Серьезно, вы должны!
Честно говоря, мне трудно понять, почему вы не хотели бы использовать Nx для своего приложения Angular. И нет, вам не нужен монорепо. Позвольте мне объяснить это вам.
Многим людям сложно настроить структуру папок и архитектуру приложений, которые просты в использовании, могут расширяться с течением времени и которыми может управлять большая команда. Это сложно для полирепозиториев и еще сложнее для монорепозиториев. Но независимо от того, работаете ли вы с polyrepo или monorepo, Nx может вам помочь.
Кратко — что такое Nx?
Nx — это мощная система сборки с открытым исходным кодом, которая предоставляет инструменты и методы для повышения производительности разработчиков, оптимизации производительности CI и поддержания качества кода. — Nx docs.
Я взял это прямо из официальных документов. Для меня Nx — это надежный краеугольный камень для любой архитектуры приложений Angular. Я создал массу приложений с помощью Nx — и позвольте мне сказать вам, что это как иметь полезного приятеля на этом пути.
Nx подталкивает вас к:
- Структурированию вашей кодовой базы в четко определенные модули для лучшей управляемости
- Обеспечению последовательной настройки за счет систематического использования генерации кода
- Избегайте потенциальных ловушек беспорядочных зависимостей, которые могут поставить под угрозу ремонтопригодность вашего кода.
- Помогает вам автоматически визуализировать вашу структуру с помощью графика зависимостей и многое другое.
Хотя Nx закладывает основу для успеха, он не обещает победы. Вы все еще должны придерживаться лучших практик, выбирать метод, проверенный в бою (например, DDD или FDD), определять *границы модулей и так далее.
После того, как вы все правильно настроили, добавление новых функций и развитие вашего приложения не составит труда. Но давайте начнем с первого шага.
Большое решение
Программные проекты могут быть большими, маленькими, простыми, сложными и иметь разные настройки команды. Таким образом, решение о том, как настроить ваш проект, действительно зависит от нескольких факторов, таких как размер вашей команды, количество приложений, которые вы создаете, размер вашей кодовой базы и объем кода, которым вы делитесь между проектами.
Выбор между полирепозиторием и монорепозиторием — это важное решение, и ваша команда должна сесть и обсудить это с вашим руководителем или архитектором. Будет еще лучше, если этот человек разбирается в приложениях Angular, настройках команды, рабочих процессах и во всех этих высокоуровневых деталях.
Специфический подход Nx
Теперь давайте сравним подход монорепозитория Nx с подходом без монорепозитория Nx на примере приложения Angular.
С Nx — в обоих случаях вы должны создавать свои функции в виде библиотек. Не отчаивайтесь на этом шаге. Наличие вещей в виде библиотек позволяет Nx творить чудеса, и для вас это почти то же самое, что и простые каталоги.
Наше приложение будет иметь две библиотеки: Tasks для функций, связанных с задачами, и Users для функций, связанных с пользователем.
Настройка монорепозитория Nx
Подход Monorepo
Подход Monorepo, по сути, заключается в том, чтобы поместить все тесно связанные проекты в одну большую коробку — единый репозиторий.
Звучит пугающе, не так ли? Вот почему многие люди сразу же игнорируют Nx — потому что думают, что это только для монорепозиториев. Это не так. Но я объясню это позже, а пока давайте сосредоточимся на монорепозитории.
Ключевые этапы и отличия:
- Создание рабочей области: рабочая область Nx создается с помощью
npx create-nx-workspace@latest — preset=angular-monorepo
. - Создание приложения: мы создаем приложение Angular внутри рабочей области, используя диспетчер задач
npx nx generate @nrwl/angular:app
. - Генерация библиотек:
npx nx g @nx/angular:library tasks, npx nx g @nx/angular:library users
- Управление зависимостями: в монорепозитории все приложения и библиотеки используют одни и те же
node_modules
, что упрощает управление зависимостями. - Сборка приложения: Команда
npx nx build task-manager
собирает приложение. Благодаря расширенному кэшированию вычислений Nx время сборки может быть значительно сокращено в настройке монорепозитория. Будет создана только та часть приложения, для которой вы внесли изменения.
task-management/
├── apps/
│ ├── task-manager/
│ │ ├── src/
│ │ │ ├── app/
│ │ │ ├── main.ts
│ │ │ ├── index.html
│ │ │ ├── ...
│ │ ├── angular.json
│ │ ├── ...
│ ├── task-manager-e2e/
│ │ ├── ...
├── libs/
│ ├── tasks/
│ │ ├── src/
│ │ │ ├── lib/
│ │ │ ├── index.ts
│ │ │ ├── ...
│ │ ├── ...
│ ├── users/
│ │ ├── src/
│ │ │ ├── lib/
│ │ │ ├── index.ts
│ │ │ ├── ...
│ │ ├── ...
├── node_modules/
├── package.json
├── nx.json
├── project.json
├── ...
Здесь все приложения хранятся в каталоге apps/
, а библиотеки — в каталоге libs/
. Они используют один и тот же каталог node_modules/
, в котором находятся зависимости для всего рабочего пространства.
Преимущества:
- Совместное использование кода: Monorepo позволяет легко обмениваться кодом между различными приложениями и библиотеками. Это может значительно уменьшить дублирование кода в проектах с несколькими приложениями, имеющими общие функции. Все это находится в одном репозитории, благодаря чему ваша IDE знает буквально обо всем. Больше не нужно беспокоиться о пакетах NPM.
- Атомарные изменения: изменения в нескольких проектах могут быть зафиксированы одновременно (это просто «ветвь git»), что упрощает отслеживание. Nx достаточно умен, чтобы создавать/тестировать только то, на что повлияло ваше изменение. Так, например, только 2 из 20 приложений и 5 из 100 библиотек.
- Унифицированная настройка сборки и тестирования. Все проекты находятся в одном месте, поэтому вы можете создавать, тестировать и выпускать их все вместе. Настраивать и поддерживать бесперебойную работу интеграционных тестов проще, когда все проекты находятся под одной крышей.
- Упрощенное управление зависимостями: все ваши проекты имеют одни и те же зависимости. Теоретически существует способ иметь несколько разных версий, однако команда Nx строго поощряет использование одной версии. Итак, есть только один файл package.json, о котором вам нужно беспокоиться. Это также обеспечивает синхронизацию всего. Вам нужно проделать больше работы во всех приложениях, чтобы убедиться, что все работает нормально после обновлений, что в конечном итоге хорошо для проекта.
- Согласованность кода: легче убедиться, что все играют по одним и тем же правилам, когда все ваши проекты находятся в одном месте. Вы можете назначать право собственности на определенные приложения/компоненты командам/людям в вашей организации. Вы предоставляете простой способ адаптации новых разработчиков — они могут использовать генераторы кода, а вы следите за тем, чтобы структура всегда соответствовала ожиданиям.
- Упрощенная адаптация: новым разработчикам легче начать работу, когда все находится в одном месте.
Монорепо тоже не идеален. Вот несколько вещей, на которые следует обратить внимание:
Недостатки:
- Масштабируемость. По мере расширения вашей кодовой базы время, необходимое для сборки и тестирования, также может увеличиваться. Тем не менее, Nx отлично справляется с этой задачей благодаря кэшированию вычислений и затронутым командам. Однако большие кодовые базы все же могут привести к снижению производительности IDE и увеличению времени тестирования, сборки и CI.
- Повышенная сложность: монорепозиторий может стать сложным, особенно с большими кодовыми базами и командами. Вы должны быть очень строгими и иметь установленные правила, чтобы легко поддерживать порядок.
- Конфликты слияния. Когда несколько команд работают над разными приложениями в одном репозитории, увеличивается вероятность конфликтов слияния.
- Контроль доступа для чтения: в мире Monorepo каждый обычно получает доступ для чтения ко всему. Нет простого способа ограничить доступ для чтения к конкретным проектам. Это может быть не лучшим вариантом, если вам нужен больший контроль над тем, кто к чему прикасается.
- Обзоры кода: с потенциально большими объемами изменений, обзоры кода могут показаться чрезмерными. Потенциально вы можете решить эту проблему, назначив «владельцам кода» определенные части.
Настройка Nx без монорепозитория
Подход Polyrepo
Давайте поговорим о подходе Polyrepo. Здесь каждый проект получает свое личное пространство — свой отдельный репозиторий. Если вы большая организация, вам, возможно, придется манипулировать между 10–20 отдельными репозиториями.
Ключевые этапы и отличия:
- Создание рабочей области: при создании рабочей области Nx для автономной установки мы используем
npx create-nx-workspace@latest
, выбираемStandalone Application
и называем приложениеtask-manager
. - Генерация библиотек:
npx nx g @nx/angular:library tasks, npx nx g @nx/angular:library users
- Сборка приложения: Команда
npx nx build task-manager
собирает приложение. Кэширование вычислений в Nx также работает в автономном режиме, но оказывает меньшее влияние, поскольку есть только одно приложение.
task-manager/
├── src/
│ ├── app/
│ ├── main.ts
│ ├── index.html
│ ├── ...
├── libs/
│ ├── tasks/
│ │ ├── src/
│ │ │ ├── lib/
│ │ │ ├── index.ts
│ │ │ ├── ...
│ │ ├── ...
│ ├── users/
│ │ ├── src/
│ │ │ ├── lib/
│ │ │ ├── index.ts
│ │ │ ├── ...
│ │ ├── ...
├── node_modules/
├── project.json
├── nx.json
├── package.json
├── ...
Здесь структура проще. Приложение и его исходные файлы находятся в корне проекта. Библиотеки по-прежнему находятся в каталоге libs/
, но вы можете назвать этот каталог как хотите. Вы также можете иметь несколько каталогов libs.
С подходом без монорепо вы все равно получаете все это из коробки:
- Готовое приложение Angular в корне рабочей области Nx (
src/app
) - Тест e2e на основе Cypress (
e2e/
) - Предварительно настроен Prettier
- ESLint предварительно настроен
- Jest предварительно настроен
Преимущества:
- Упрощенная структура проекта. Автономная установка имеет более простую структуру проекта, что упрощает ее для небольших команд или для тех, кто только начинает работать с Nx. Один репозиторий равен одному проекту, что упрощает понимание и поиск в кодовой базе.
- Изоляция. Автономная установка обеспечивает изоляцию приложений друг от друга. Это выгодно, когда у приложений мало общего или когда требуется строгая изоляция между ними. Каждый репозиторий — это отдельный остров, поощряющий вас писать автономный код, что может привести к более высокому качеству кода.
- Конкретные конфигурации. Автономные приложения могут иметь свои собственные конфигурации, обеспечивая гибкость, когда у разных приложений разные требования.
- Контролируемый доступ для чтения: вы сами решаете, кто может войти, а кто нет. Это означает, что вы можете ограничить доступ для чтения к определенным приложениям или частям вашей кодовой базы, что делает Polyrepos хорошим выбором, если разным командам или людям нужны разные уровни доступа для чтения.
- Управляемые проверки кода. Проверка кода доставляет меньше головной боли, поскольку изменения обычно прячутся в определенных репозиториях.
Но полирепо не идеальны. На пути могут быть неровности.
Недостатки:
- Дублирование кода: совместное использование кода между проектами может превратиться в праздник копирования и вставки, если вы не будете осторожны. Или вы можете в конечном итоге поддерживать 10 пакетов NPM в своих приложениях и изо всех сил пытаться поддерживать все в актуальном состоянии с последними версиями. Автономные установки не способствуют совместному использованию кода так же эффективно, как монорепозитории, что делает их менее подходящими для проектов с несколькими приложениями, имеющими общие функциональные возможности.
- Несколько конфигураций сборки: если у вас есть несколько автономных приложений, для каждого из них может потребоваться отдельная конфигурация сборки.
- Управление зависимостями: это может быть немного сложно. Каждый проект имеет свой собственный файл package.json, и вы можете столкнуться с разными версиями сторонних зависимостей в разных проектах.
- Координация изменений. Внесение изменений, затрагивающих несколько проектов одновременно, может оказаться непосильной задачей. Для исправления одной функции или ошибки могут потребоваться изменения в нескольких разных репозиториях.
- Сложные интеграционные тесты. Настройка и поддержание бесперебойной работы интеграционных тестов в разных репозиториях может быть более сложной задачей по сравнению с настройкой монорепозитория.
Перейти с Nx
Выбор между монорепозиторием и настройкой без монорепозитория (полирепозиторий) действительно сводится к тому, что нужно вашему проекту. Если у вас есть большой проект с большим количеством общих материалов, вам может подойти монорепозиторий. Но если ваш проект меньше или вам нужно хранить вещи отдельно, иметь лучший контроль над ограничениями доступа для чтения, тогда может подойти автономная установка.
У обоих есть свои плюсы и минусы, но, как упоминалось ранее. Неважно, какой из них вы выберете. У Nx есть что предложить вам для обоих вариантов.
Я не вижу причин не запускать проект Angular без Nx в качестве компаньона. Для подхода monorepo или polyrepo.