В продолжении к предыдущей статьи, погружение в nx. Если не знакомы с nx, рекомендую сначала прочитать ее. Практический урок по написанию собственного плагина. Реализуем generator и executor. generator - при запуске которого у нас будет обновлять корневой файл в проекте projects.json, в которой будем вносить все существующие приложения. Получившийся результат (проект) можно посмотреть здесь. А executor будет брать этот файл, читать и выводить в консоль содержимое этого файла. Пример достаточно простой и не является рекомендацией к его применению на реальных проектах, но дает понять как работают generator и executor. А в конце статьи расскажу про реальные кейсы. generator чаще всего вызывается через терминал. Создание собственного generator позволяет упростить повторные операции создания файлов и(-или) папок, как в корне монорепы, так и создавать приложения и библиотеки в ней. Также можно вносить изменения уже в существующие файлы и папки. На сайте nx.dev проекта также можете ознакомится с простым примером создания generator. А мы в свою очередь реализуем собственный (листайте ниже). Например, у плагина @nx/react есть generator создания библиотеки: nx g @nx/react:lib my-new-lib или например для нового микрофронта: nx g @nx/react:app my-new-app или создания нового реакт компонента nx g @nx/react:component my-new-component --project=my-new-app  Можно в принципе зайти в исходники его и взять какие-нибудь решения для своего решения. Позволяет производить различные манипуляции с приложением, библиотекой. Например: запускать тесты, проверка качества кода, сборка, запуск в режиме разработки и т.д. Под свои нужды можно создать что угодно. Чуть больше информации то, для чего нужен executor и как с ним работать тут. Как и для generator, для executor на сайте проекта также есть пример. Главное, что executor необходимо указывать в файле project.json приложения или библиотеки. Созданный executor помещается в свойство executor, в options передаются параметры, которые принимает executor. Названия, по которым потом мы будем взаимодействовать с приложением или библиотекой, указываются в targets, например: build, test и т.д. Итак, приступим к практике. За основу возьмем шаблон приложения для react. Начнем с создания приложения: Выбираем react На вопрос про framework, отвечаем N. Затем выбираем integrated monorepo. Application name оставляем тот же.  Сборщик выбираем webpack. По стилизации оставляем css. На вопрос "Enable distributed caching to make your CI faster" отвечаем N, т.к. не планируем использовать распределенных кэш разработчиков nx. Микрофронтенды (приложения) будут находится в папке apps, а библиотеки в libs. После выбора необходимо подождать пару минут, чтобы зависимости установились и проект настроился для первоначальной загрузки. Если у вас не установлен nx глобально, то можем это сделать так: Запустить приложение в режиме разработке можно так nx serve myorg Где myorg - название проекта в папке apps, а serve это target, который указан в файле project.json (apps/myorg)  Более детально почитать по тому, что можно делать в текущем окружении можно тут. Там описано как добавлять к монорепе еще микрофронты и библиотеки. Для начала создадим новый микрофронтенд: После выполнения команды, в папке apps появится еще приложение(микрофронтенд) - geek и папка для end-to-end тестов. В итоге, в папке apps у нас два приложения. А также создадим библиотеку: На все вопросы отвечаем нет. В файле tsconfig.base.json можно заметить, что добавилась строка @myorgg/list": ["libs/list/src/index.ts"],  ее добавляет generator плагина react (@nx/react). Добавляется для того, чтобы мы могли в коде использовать импорт библиотеки через публичный интерфейс (public api). Теперь можно приступить к разработке плагина. Для того чтобы воспользоваться generator плагина, необходимо установить зависимосить: Создадим свой плагин: После выполнения команды в папке libs/my-plugin/src появится папка generator. Перейдем в нее и найдем generator/my-generator. В файле schema.json указываются правила к полям, которые будут проверятся при запуске executor или generator. Непосредственно nx запускает файл generator.ts. У generator также может быть папка files, эти файлы будут копироваться в место назначения. Обновим файл schema.json: Файл schema.d.ts можем удалить, т.к. у нас нет входных параметров. Также удалим файл generator.spec.ts, нас не интересуют тесты в данной статье. Папку files тоже удалим, т.к. мы ничего не копируем, за исключением создания файла apps.json в корне проекта. Откроем файл generator.ts и заменим содержимое на это: Проверить работу generator можем так:  nx generate @myorg/my-plugin:my-generator Теперь в корне репозитория создается файл apps.json с таким содержимым: ["geek", "geek-e2e", "myorg", "myorg-e2e"]. В условие можно еще указать, чтобы имена проектов -e2e не попадали в файл. Обновим файл project.json библиотеки libs/list: Мы добавили строку generate: {executor: @myorg/my-executor"}, это значит, что мы можем теперь запустить данный executor так: Где generate это имя targets, а list - имя проекта. Например мы не сможем такую же команду использовать для приложения geek или myorg, необходимо явно указать в targets файла project.json. Внес правки в файл executor.ts sucess необходимо возвращать, чтобы дать понять nx, что успешно или не успешно выполнилась команда. После выполнения команды выведется в консоль список приложений из файла apps.json. В примерах выше я постарался как можно проще написать инструкции по взаимодействую с собственным плагином. nx/devkit позволяет использовать граф зависимостей tree в generator, и извлекать полезные данные, не реализую самостоятельно обход по директориям и чтения файлов проектов. А executor в свою очередь кроме options, вторым аргументом принимает executorContext, который содержит множество полезных свойств.  nx это всего лишь инструмент для того, чтобы определенные "сценарии" в проекте упростить, стандартизировать. Но это не значит что вам данный инструмент подойдет. Прежде чем его внедрять, необходимо понимание, что ваших компетенций достаточно чтобы адаптировать этот инструмент для вашего проекта, а также ВРЕМЯ. Так как будут трудности на начальном этапе при его изучении, так и определенные вызовы, которые вам придется решать. Мне пришлось ни один раз прочитать документацию, чтобы полностью понять основные особенности этого инструмента и то, как следует его применять. А еще полазить по исходникам с отладкой в консоли. Если возникнут вопросы или трудности, пишите в комментарии, постараюсь ответить. Начну с того, что у нас проект уже существовал. И необходимо было переехать с минимальными трудностями для разработчиков, чтобы они не заметили переезда. А в конечном итоге упростить их работу. Этих целей удалось достичь. Можно было ограничиться переездом на yarn workspaces, но тогда нам пришлось писать множество инструментов для работы с пространством, проверки качество кода и т.д. Поэтому решили пойти по пути меньшего сопротивления и большей эффективности в нашем случае. Но на yarn мы все равно перешли, но только в роли пакетного менеджера. Но учитываем, что pnp у yarn по умолчанию, необходимо создать файл .yarnrc в проекте и указать nodeLinker: node-modules, чтобы nx взаимодействовал с пакетами корректно. Переход на yarn увеличил скорость установки пакетов в разы. Раньше разработчик ждал по 10-15 минут при первоначальной установки пакетов. Теперь это может занимать 1-2 минуты. Вообще чем nx понравился, так это графом зависимостей, что можно упростить себе жизнь при развертывании приложений. Допустим, у нас изменилась библиотека, а эта библиотека используется в нескольких микрофронтах. Благодаря команде nx affected, у нас есть возможность запустить множественную сборку микрофронтов, которые зависят от данной библиотеки. А теперь о самом плагине в проекте: реализовали generator для микрофронтедов, библиотек и для создания динамического файла env проекта (берутся переменные окружения и подставляются в результирующий файл, который в свою очередь загружается клиентом и используется микрофронтами). реализовали executor для webpack. Стандартное @nx/webpack решение не подошло по двум причинам: часть плагинов и настройки жестко забиты и их нельзя убрать без костылей, обязательно требует чтобы некоторые файлы в проекте присутствовали. У нас например микрофронты лишены своего файла webpack.config.js, executor использует один общий и подставляет определенные настройки под определенные сценарии. хотелось бы иметь один общий файл для микрофронтов, где будет хранится название микрофронта, занимаемый его порт и название окружения. Это позволяет создавать новые микрофронты с произвольными портами проще, а разработчику сразу понять на каком порту у него будет определенный микрофронтенд и какие окружения он поддерживает.  Веб-разработчик