В экосистеме Node.js существует довольно много библиотек и фреймворков, которые пользуются определенной популярностью в сообществе. Но ни один из инструментов не решил главную проблему, с которой сталкиваются разработчики, когда пытаются писать бэкенд на Node.js. Это проблема выбора архитектуры. Хочу обратить ваше внимание на относительно молодой фреймворк Nest.js. Из коробки он предлагает заранее предопределенную архитектуру, которая заточена под максимально удобную поддержку и масштабируемость вашего приложения. Заложенные архитектурные подходы проверены временем и давно используются в других, более зрелых платформах: Java(Spring), Python(Django), PHP(Laravel) и прочих. Авторы Nest.js не скрывают, что их вдохновил один из популярных фреймворков для клиентских приложений — Angular.js, а его авторы ориентировались на походы, используемые в Java и C#. Если вы знакомы с Angular.js, то увидите в Nest.js много схожих идей. Разберем основные концепции, на которых строится разработка Nest.js-приложений. Базовым строительным блоком приложения является модуль. Для его определения существует специальный декоратор @Module(). Модуль содержит в себе какую-либо логику, которая удовлетворяет принципу единой ответственности. Например, это может быть модуль авторизации пользователей, модуль работы с товарами или модуль пользовательских рассылок. Структура модулей приложения представляется в виде графа, согласно которому любое Nest.js-приложение должно иметь в cвоей основе так называемый корневой модуль. В нем группируются остальные модули. Внутри себя каждый модуль организует работу других строительных блоков приложения: контроллера и провайдеров. Немного позже мы разберем их подробно. Ниже приведен пример определения модуля. Другой тип строительных блоков — это контроллеры. Они отвечают за обработку входящих запросов и возврат ответа клиенту. Контроллеры определяются с помощью декоратора @Controller(). В качестве аргумента в него передается строка, которая назначает корневой путь для входящих запросов. Так как каждый контроллер принадлежит конкретному модулю, он автоматически будет удовлетворять принципу единой ответственности. То есть каждый контроллер сосредоточен на запросах клиента для одной конкретной функциональности. Давайте рассмотрим наглядный пример определения контроллера по работе с пользователями. Nest.js содержит и другие декораторы запросов, с помощью которых можно реализовать API в стиле CRUD или REST: @Get, @Post, @Put, @Delete. Провайдеры предназначены для инкапсуляции логики самого приложения. Это может быть как бизнес-логика, так и инфраструктурная логика. На уровне провайдеров используется один из популярных и привычных нам паттернов — внедрение зависимостей. Таким образом мы можем внедрять провайдеры в контроллеры или другие высокоуровневые провайдеры. Для определения провайдера используется специальный декоратор @Injectable().  Также стоит упомянуть, что провайдеры иногда называют сервисами по примеру того, как эти элементы именуются в других фреймворках.  Давайте рассмотрим пример определения провайдера и встраивания его в контроллер. Помимо этого в Nest.js существуют другие прикладные строительные элементы: middlewares, pipes, guards, interceptors. Ознакомиться с ними подробнее можно в официальной документации. Здесь мы рассмотрели самые основные. В приложениях, реализованных на Nest.js, любой модуль системы имеет свой жизненный цикл. Это позволяет назначать обработчики событий перехода из одной фазы цикла в другую. Существует 4 фазы: onModuleInit — срабатывает один раз в момент инициализации модуля; onApplicationBootstrap — срабатывает один раз при запуске приложения; onModuleDestroy — срабатывает один раз в момент уничтожения модуля; onApplicationShutdown — срабатывает один раз при завершении работы приложения. Приятным бонусом является то, что Nest.js имеет в своем наборе удобный cli-интерфейс. Для изучения поддерживаемых команд можно воспользоваться командой для вывода справки. Или если вам нужна справка по какой-то конкретной команде: С помощью cli можно развернуть структуру нового проекта, сгенерировать полный набор строительных элементов (контроллеры, модули, провайдеры и пр.) и модульные тесты к ним, а также управлять запуском приложения в различных режимах. Описание работы с базами данных требует отдельной статьи. Но здесь я хотел бы рассказать, что у Nest.js есть полноценная интеграция с SQL и NoSQL-базами. Предлагается на выбор несколько ORM. Наиболее популярные из них это Sequelize (@nestjs/sequelize) и TypeORM (@nestjs/typeorm). Для работы с MongoDB используется классический драйвер Mongoose (@nestjs/mongoose). Давайте рассмотрим пару примеров работы с TypeORM. Фрагмент кода, описывающий подключение к БД: И пример определения сущности: В плане тестирования у Nest.js тоже всё хорошо: Можно автоматически генерировать кодовую структуру модульных тестов для компонентов системы и e2e-тестов для самого приложения. Из коробки есть дефолтный test-runner, который может запускать тесты изолированно для каждого модуля. Также имеется полноценная интеграция с популярным фреймворком для тестирования — Jest. Используемый подход внедрения зависимостей позволяет легко мокировать компоненты системы при их запуске в тестовом окружении. Пример простого модульного теста: А это пример e2e-теста: Предлагаю подытожить и определить преимущества, ради которых стоит обратить внимание на  Nest.js: Архитектура. В основе фреймворка лежат правильные архитектурные подходы, которые позволяют разработчику идти по уже намеченному пути и не допускать ошибок.  Проверка типов. Nest.js реализован на базе языка TypeScript. Думаю, что не стоит расписывать, какие возможности открывает этот язык. При этом не запрещено использовать обычный JavaScript. DI. Внедрение зависимостей позволяет держать сервисы изолированными от остальной логики, а их код — более поддерживаемым и читаемым. Тестирование. Из коробки Nest.js предоставляет полностью интегрированную и настроенную среду для написания и запуска модульных и e2e-тестов.  Я хотел обратить внимание сообщества на Nest.js. По моему мнению, в ближайшем будущем его популярность среди разработчиков будет расти. Инструмент привносит системность в подходы к разработке сервисов на Node.js. И благодаря тому, что он первый двинулся в сторону решения архитектурных проблем, мы можем ожидать, что через пару лет он будет занимать весомую долю этой ниши.   IT Area Lead