Как ранее было отмечено в предыдущем посте концепция рабочего каталога Angular закономерно эволюционировала до поддержки полноценных workspace - проверенный и понятный способ управления сложностью при масштабировании процесса разработки (Visual Studio Solution , SBT Multi-Project builds , Gradle Multi-Project Builds , RushJS , Lerna и др. ).

Для каждого, кто практически сталкивался с Angular проектом средней руки, не будет секретом, что angular.json может легко содержать тысячи строк убористого JSON, с невероятным, даже нарочито избыточным количеством дублирующейся информации. Проблема отнюдь не новая и дающая о себе знать при масштабировании процесса разработки сложного продукта. Компактность и человеко-читаемость формата явно не была в приоритетах, и как-бы намекает, что человеку тут и нечего делать. Из этого и будем исходить.

Некоторые проблемы

  1. Многословность. Ориентироваться в длинной "портянке" весьма некомфортно. При внесении изменений есть высокий риск сделать их не в том месте. Что, так же, затруднает понимание при анализе истории изменений.

  2. Нарушение принципа DRY. При изменении путей к файлам необходимо аккуратно вносить множественные идентичные измененения во множестве различных параметров.

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

Вариант решения проблем

  1. Стандартом de facto в отрасли для конфигурационных файлов стало использование YAML, как чуть более human friendly формата с точки зрения восприятия. Его опциональная поддержка, наряду с JSON5 будет весьма полезной. Возможность определять контекстные переменные и определять значения параметров через интерполяцию частично бы избавило от заботы переопределять значения множества параметров.

  2. Декомпозиция большого фала на логически независимые, и значимые в контексте, более мелкие фалы (общие настройки, настройки конкретных проектов и т.д.) существенно упрощает и восприятие и понимание их содержимого. Спецификация JSON Reference вполне органично способна решить эту задачу, а так же открывает возможности прямого переиспользования типичных настроек, вместо их множественного копирования.

  3. После того, как будет выполнена декомпозиция файла angular.json на логические составляющие, то настройки проектов логично хранить в папках соответствующих проектов.

Как только всё будет готово, то останется выполнить обратную задачу: для каждого проекта вычислить все значения параметров на основе контекстно определённых переменных и $ref ссылок, и далее объединить все итоговые проектые конфигурации с глобальными настройками в единый angular.json файл.

Пример реализации

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

У нас получился инструмент ngx-ws, на примере которого далее и рассмотрим как идея работает на практике.

Подготовка

Создадим небольшой простой workspace c группой проектов.

Декомпозиция

Преобразуем полученный angular.json в YAML формат, декомпозируем его на файлы angular-workspace.yaml и серию файлов angular-project.yaml отдельно для каждого проекта.

Содержимое оригинального JSON поместим в свойство angular для angular-workspace.yaml, а конфигурацию каждого проекта в свойство project для каждого angular-project.yaml

Интерполяция

Файлы поддерживают секцию vars, которая определяет контекстные переменные файла. Для angular-project.yaml переменная name предопределена именем соответсвующего проекту каталога и её объявлять не обязательно. Для библиотек получим примерно вот такую картину:

Примечание: Кавычки для значения параметров обязательны.
Примечание: Кавычки для значения параметров обязательны.

Поскольку, по очевидным причинам, такое определение для всех библиотек в нашем случае (в общем случае для всех проектов одного типа) будет идентичным, то определение можно перенести в angular-workspace.yaml:

а само определение переписать в значительно более компактном виде:

Глобальная предопределённая переменная wsPath содержит полный путь
angular-workspace.yaml файла и инструкция реализует стандартный механизм ссылки на внешние ресурсы.

Точно так же можно переиспользовать значения внутри отдельного файла.

Ресурсы

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

Определяем:

Подключаем:

Получается вот так:

Сборка

Устанавливаем пакет

npm i -g ngx-ws

Запускаем сборку

rm angular.json; ngx-ws -v

или, в нашем случае, выполнить

npm run rebuild

Видим, что сгенерированный angular.json идентичен оргинальному. Команду можно (хотя и совсем не обязательно) включить в пайплайн CI-сборки или разработки, а файл angular.json рассматривать как автоматически генерируемый.

Заключение

Рассмотрены лишь некоторые аспекты. Есть и другие, такие как полноценная локализация в файловой структуре зависимостей проектов, как, например, это сделано в RushJS . В целом, данный подход хорошо зарекомендовал себя на практике и успешо используется в ряде проектов на протяжении уже нескольких лет. В дизайн решения заложена совместимость с потенциальными изменениями в формате angular.json и стандартными toolchain экосистемы, что практически сводит к минимуму риски, связанные с его внедрением, в то же время, решая вышеописанные проблемы.

Ссылки

Комментарии (3)


  1. lehkap
    15.11.2021 07:56
    +3

    Имхо, yaml не более человеко-читаемый, а самое главное намного менее человеко-редактируемый формат, по сравнению с json.


    1. Launcelot
      15.11.2021 10:27

      полностью согласен с вами


    1. saaivs Автор
      15.11.2021 10:32

      С вами сложно не согласиться. Особенно в части человеко-редактируемости. Поэтому поддержка YAML не более чем возможность, чтоб просто обеспечить выбор. Всё описанное в посте будет работать точно так же, если вместо YAML будет JSON5.