Добро пожаловать в мир легкой серверной разработки с Nest JS! В этом захватывающем путешествии мы узнаем, как Nest JS революционизирует создание серверных проектов, делая его проще, чем когда-либо прежде.

В отличие от других фреймворков, которые утопают в шаблонном коде даже для простого примера «Hello World», Nest JS упрощает процесс, автоматизируя рутинные задачи, позволяя вам сосредоточиться на сути вашего приложения.

Благодаря своим комплексным решениям для основных внутренних компонентов, таких как авторизация, аутентификация, контроллеры и GraphQL, Nest JS позволяет разработчикам с легкостью создавать надежные и масштабируемые приложения.

Обязательно ознакомьтесь с моей предыдущей вводной статьей для всестороннего обзора!

Контур:

I. Технические требования

  • Инструменты
  • Концепции

II. Начало работы с Nest JS

  • Установка Nest CLI и создание нового проекта Nest JS
  • Обзор сгенерированной структуры проекта и файлов
  • Обзор установленных пакетов и зависимостей

III. Запуск приложения Nest JS

  • Запуск сервера с помощью Nest CLI
  • Понимание того, как сервер обрабатывает входящие запросы

IV. Изучение src/main.ts

  • A. Обзор файла main.ts как точки входа в приложение
  • Понимание метода create и его параметров
  • Изучение метода app.listen и указание номера порта

V. Изучение src/app.module.ts

  • Обзор модулей в Nest JS
  • Импорт и настройка контроллеров и провайдеров

VI. Изучение src/app.controller.ts

  • Понимание роли контроллеров в обработке входящих запросов
  • Анализ класса AppController и его зависимостей
  • Изучение декоратора класса Controller и его использования

VII. Заключение

Технические требования

Чтобы отправиться в путешествие по Nest JS, вам понадобится следующее:

  1. Node JS и NPM: убедитесь, что на вашем компьютере установлены Node JS и NPM. Эти инструменты послужат основой для запуска приложений Nest JS.
  2. Nest CLI: глобально установите Nest CLI с помощью NPM. Nest CLI предоставляет интерфейс командной строки, который упрощает создание и управление проектами Nest JS.
  3. Основы языка TypeScript: ознакомьтесь с основами TypeScript, так как Nest JS использует этот расширенный набор JavaScript для создания надежных и статически типизированных приложений.
  4. Ваша любимая IDE: выберите предпочитаемую интегрированную среду разработки (IDE) для написания кода. Visual Studio Code (VS Code) — популярный выбор среди разработчиков благодаря обширным функциям и экосистеме.
  5. Понимание концепций API: получите общее представление об интерфейсах прикладного программирования (API) и о том, как они служат конечными точками для связи между различными программными компонентами.

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

Создание приложения Hello Nest с помощью интерфейса командной строки

Создание серверных проектов никогда не было таким простым, как в случае с Nest JS.

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

Мы установим CLI с помощью NPM (обратите внимание, что для установки CLI можно использовать другие менеджеры пакетов). Итак, используйте следующую команду для глобальной установки CLI:

npm install -g @nestjs/cli

У вас есть возможность установить CLI глобально (используя параметр -g), но учтите, что если вы работаете над несколькими проектами, все они будут обслуживаться с использованием одной и той же версии глобально установленного CLI.

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

nest new <project-name>

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

Затем вам будет предложено выбрать менеджер пакетов для проекта; Я выберу нпм.

На следующем рисунке показан процесс установки в действии из терминала:

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

  • app.controller.ts: обрабатывает входящие запросы, чтобы определить, какую функцию выполнять.
  • app.module.ts: группируйте связанные сервисы, контроллеры и объекты для организации кода.
  • app.service.ts: содержит всю бизнес-логику.
  • main.ts: служит точкой входа для нашего приложения Nest JS. Он устанавливает экземпляр приложения Nest и запускает сервер.

Мы рассмотрим их более подробно через некоторое время.

Также вместе с проектом были установлены некоторые пакеты и зависимости:

  • @nestjs/common: содержит подавляющее большинство функций, классов и т. д., необходимых для начала работы с Nest.
  • @nestjs/platform-express: Поскольку Nest сама не может обрабатывать HTTP-запросы, она полагается на стороннюю реализацию, такую ​​как Fastify или Express JS (последнюю мы используем здесь).
  • reflect-metadata:помогает декораторам работать.
  • typescript: Включено, поскольку наши приложения Nest будут разрабатываться с использованием Typescript (хотя это не является строго обязательным, поскольку вы также можете использовать JavaScript).

Фактические пакеты находятся в каталоге nodeModules, а версии и зависимости каждого пакета можно найти в файле package.json.

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

Запуск вашего приложения

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

Используя интерфейс командной строки Nest, вы можете запустить свое приложение, введя следующую команду в своем терминале:

nest start

Эта команда вызовет соответствующую команду, которая находится в файле package.json в разделе сценариев, а именно:

npm run start

После запуска ваше приложение Nest начнет прослушивать входящие HTTP-запросы на указанном номере порта. Вот скриншот терминала после запуска Nest Start:

Как видно на Рис. 2, сервер Nest работает и готов обрабатывать наши запросы; большинство событий, происходящих на нашем сервере, регистрируются в терминале с отметкой даты/времени, как показано.

Теперь вас может интересовать конкретный номер порта, на котором обслуживается ваше приложение, и то, как оно обрабатывает эти входящие запросы. Кроме того, вам может быть любопытно, были ли уже определены какие-либо конечные точки. Чтобы ответить на эти вопросы, давайте изучим файлы, которые Nest CLI уже создал для нас.

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

Изучение: src\main.ts

main.ts — это класс входа приложения, используемый для создания экземпляра приложения Nest (через метод create). Он содержит функцию начальной загрузки, которая запускает метод NestFactory.create(AppModule). Этот метод принимает следующие параметры:

  • Класс начального (корневого) модуля приложения.
  • Список параметров для инициализации приложения Nest (как необязательный параметр), который создаст экземпляр вашего приложения Nest.

Обратите внимание, что вы можете создать экземпляр с указанным HTTP-адаптером (Express JS, Fastify или любым другим HTTP-адаптером для обработки цикла запрос/ответ).

Этот метод возвращает обещание, которое при разрешении содержит ссылку на экземпляр приложения Nest. Когда метод create возвращает обещание, вы можете вызвать метод .listen(portNumber), который начнет прослушивать входящие HTTP-запросы. Этот метод принимает номер порта в качестве параметра, и вы можете дополнительно передать функцию обратного вызова, которая будет выполняться после запуска сервера.

Поскольку приложения часто запускаются в разных средах с разными значениями, обычно номер порта хранится в файле .env (файл переменных среды). Файл .env содержит информацию, которая может меняться от одной среды к другой, например, имя пользователя и пароль для базы данных или почтового сервера, определенные флаги для отключения аутентификации во время разработки, каталог для хранения загруженных файлов и бесконечные переменные. . Подробнее о файлах окружения читайте здесь!

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

Это ответ на один из наших вопросов: «На каком порту обслуживается ваше приложение?» Теперь мы знаем, что это указано в src/main.ts, особенно в методе app.listen(portNumber).

Теперь давайте рассмотрим файл main.ts построчно. Взгляните на Рисунок 3, на котором представлен базовый код автоматически сгенерированного файла main.ts:

Давайте разберем это:

  • Строка №1 импортирует класс NestFactory, содержащий метод .create(rootModule). Это используется для передачи корневого модуля (модуля точки входа) для текущего приложения из пакета @nestjs/core.
  • В строке № 2 мы импортируем AppModule (корневой модуль), который автоматически генерируется из CLI при создании приложения ранее.
  • В строке № 4 функция начальной загрузки помечена как асинхронная (обратите внимание, что ключевое слово async заставляет функцию возвращать обещание; ключевое слово await используется внутри асинхронных функций, что заставляет программу ждать разрешения обещания перед выполнением следующей строки). Основная цель функции начальной загрузки — вызвать ее для запуска приложения, и стоит отметить, что она может называться как угодно.
  • В строке № 5 выполнение приложения начинается с вызова метода NestFactory.create() и AppModule передается в качестве аргумента для представления модуля точки входа (корневого модуля). Экземпляр приложения Nest создается и сохраняется в константе приложения.
  • В строке № 6 константа приложения используется для запуска HTTP-сервера с помощью метода прослушивания событий на веб-сервере с доступным портом (по умолчанию в качестве параметра передается 3000). Метод .listen() вернет обещание, указывающее на то, что сервер успешно запущен с использованием ключа ожидания.

Нет необходимости использовать дополнительную функцию обратного вызова в методе .listen(). Поскольку метод использует ключ await, это означает, что любой последующий код гарантированно будет выполнен после того, как сервер начнет прослушивание.

  • Строка №8 просто выполняет (вызывает) функцию bootstrap.

Теперь, когда в этом файле прояснена каждая строка и мы ответили на первый вопрос «На каком порту обслуживается ваше приложение?», у вас может возникнуть вопрос: «Что такое модуль?» и «Что включает в себя AppModule, который мы импортировали в строке № 2 и передали методу .create() в строке № 5?» Давай выясним.

Изучение: src\app.module.ts

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

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

AppModule — это корневой модуль и начальная точка приложения (созданного CLI), которое импортирует все приложение. На Рис. 4 показан базовый код автоматически сгенерированного файла app.module.ts.

Разберем этот файл построчно:

  • Строка №1 импортирует декоратор класса Module из @nestjs/common. Декоратор класса Module содержит следующие свойства: imports, controllers и providers. Мы рассмотрим их в следующих нескольких строках.
  • Строка № 2 импортирует класс AppController, который является контроллером, созданным с помощью CLI. Контроллеры используются для обработки входящих запросов от клиента и выполнения соответствующей логики по запросу.
  • Строка №3 импортирует класс AppService, который также генерируется CLI. Служба — это тип поставщика, используемый для абстрагирования сложных фрагментов кода, которые могут быть внедрены в качестве зависимостей.
  • В строках с 5 по 9 показан декоратор класса Module (используемый, чтобы сообщить Nest JS, что этот класс будет действовать как модуль для нашего приложения), содержащий три свойства, которые мы упомянули в объяснении строки № 1.

Первое свойство (imports) содержит необязательный список импортированных модулей, которые экспортируют поставщиков, необходимых в AppModule.

Второе свойство (контроллеры) содержит необязательный список контроллеров, которые Nest JS будет использовать для создания экземпляра каждого контроллера при запуске приложения.

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

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

В строке № 10 класс AppModule экспортируется, чтобы его можно было импортировать в файл main.ts.

Теперь, когда мы разобрали каждую строку, вам должно быть ясно, для чего используется каждое свойство в декораторе. Далее мы разберемся с кодом, который строит контроллер, где мы ответим на оставшиеся два вопроса, которые мы упомянули в начале этого раздела: «Как мы будем обрабатывать эти запросы?» и «Есть ли еще конечные точки?»

Изучение: src\app.controller.ts

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

Давайте рассмотрим файл app.controller.ts построчно, используя Рисунок 5, на котором показан базовый код автоматически сгенерированного файла.

Разбивка кода:

  • Строка №1 импортирует декоратор класса Controller из @nestjs/common. Декоратор класса Controller требуется, чтобы Nest понимала, что класс действует как контроллер, что дает классу возможность получать запросы и генерировать ответы. Класс Controller содержит множество связанных маршрутов (конечных точек), каждый из которых обрабатывает один путь одного типа HTTP-запроса. Также мы видим, что декоратор метода Get импортирован из @nestjs/common.
  • Строка №2 импортирует класс AppService. Как уже упоминалось, службы — это внедряемые классы (поставщики), которые содержат бизнес-логику для определенного модуля; обычно контроллер выполняет действие или группу действий (методов), реализованных в конкретной службе.
  • Строка № 4 использует декоратор класса Controller, чтобы сообщить Nest JS, что этот класс будет действовать как контроллер для нашего приложения. Этот декоратор принимает необязательный параметр, называемый prefix (строка), который определяет префикс пути маршрута. Префикс добавляется к пути, указанному в любом декораторе запроса в классе (это означает, что он будет добавлен к путям методов, которые мы определим в классе). Мне нравится эта архитектура, поскольку она позволяет избежать дублирования кода и делает путь более читабельным. Например, следующий декоратор контроллера @Controller(‘/books’) будет добавлять путь /books к каждому методу внутри этого класса контроллера.
  • В строке № 5 класс AppController экспортируется, чтобы его можно было импортировать в другие модули.
  • Строка №6 является конструктором класса и используется для получения введенных провайдеров для текущего контроллера (в нашем случае AppService, который содержит внедрение бизнес-логики для маршрутов AppController). Nest разрешит AppService, создав и вернув экземпляр AppService (в форме синглтона, что означает, что если экземпляр существует где-то еще, он просто вернет его, иначе он будет инициализирован).

Примечание. Экземпляр AppService — это «readonly» и «private». Здесь «readonly» означает, что этот экземпляр доступен только в текущем классе, а свойство класса помечено как неизменяемое (оно просто защищает ссылку на внедряемый сервис, но не свойства). Это не то, что вы должны делать, это просто хорошая практика, и философия, лежащая в основе этой практики, заключается в том, что вы, вероятно, не захотите снова переназначать экземпляр. Ключевое слово «private» — это модификатор доступа (кому разрешен доступ к этому свойству или методу), другие модификаторы доступа являются общедоступными и защищенными.

  • Строка с 8 по 11 — это метод обработчика конечной точки, который используется для обработки одного пути одного типа HTTP-запроса. Более того, строка №8 — это декоратор метода Get, импортированный из пакета @nestjs/common. Декоратор метода Get используется для маршрутизации HTTP-запросов GET по указанному пути (конечной точке).

Примечание. Другие декораторы доступны для других HTTP-запросов, таких как Post, Delete, Put и Patch. На данный момент вам просто нужно понять, что декоратор Get является обработчиком определенной конечной точки для HTTP-запросов.

Вам может быть интересно, каков путь или конечная точка для достижения этого метода? Мы упоминали, что декоратор класса @Controller() принимает необязательный параметр, называемый префиксом, который определяет префикс пути маршрута для достижения каждой конечной точки в декорированном классе. Декоратор метода @Get() также может принимать необязательный параметр, который действует как конечная точка, поэтому окончательный путь маршрута для любого обработчика определяется путем объединения как необязательного префикса, объявленного для контроллера, так и пути, указанного в декораторе метода. Давайте рассмотрим пример: если префикс префикса @Controller(‘books’) сочетается с декоратором метода @Get(‘audio’), это создаст сопоставление маршрута для таких запросов, как GET ‘/books/audio’. В нашем примере и префикс, и путь маршрута пусты, что означает, что любой запрос Get к нашему приложению вызовет метод getHello().

  • Строка № 9 — это метод getHello(), который будет выполняться при запросе маршрута, связанного с декоратором метода.
  • В строке № 10 метод вернет код состояния 200 и соответствующий ответ, который в данном случае представляет собой просто строку, возвращаемую службой. Строка возвращается из метода getHello() в классе AppService; это связано с тем, что контроллер отвечает за обработку запросов только тогда, когда бизнес-логика находится в службе.

Примечание: код состояния 200 означает, что запрос выполнен успешно; это код состояния по умолчанию для всех ответов, кроме ответов Post, которые по умолчанию равны 201. Вы можете изменить код состояния с помощью декоратора метода @HttpCode(), импортированного из пакета @nestjs/common.

Изучение: src\app.service.ts

Сервисы содержат реализацию бизнес-логики для конкретного модуля; обычно контроллер будет выполнять действие или группу действий (методов) в определенном классе службы, например, контроллер @Get(‘/books’) будет вызывать определенный метод в службе (например, this.bookService.getBooks()), который будет извлекать данные, выполнять некоторую логику и возвращать результат диспетчеру.

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

Давайте рассмотрим app.service.ts file построчно, используя Рисунок 6, на котором показан базовый код автоматически сгенерированного файла.

Разбивка кода:

Наш AppService — это базовый класс с одним свойством и двумя методами. Единственная новая функция заключается в том, что он использует декоратор @Injectable().

  • Строка №1 импортирует декоратор класса Injectable из @nestjs/common. Декоратор класса Injectable необходим для того, чтобы Nest понял, что класс действует как инъекционный объект, что дает классу возможность получать
  • Служба обычно отвечает за хранение и извлечение данных, а также за выполнение бизнес-логики. Она предназначена для выполнения контроллером (в нашем случае контроллером @Get()).

Просмотрев все эти файлы, вы можете задаться вопросом, почему в вашем приложении так много фрагментов и почему, хотя это всего лишь простое приложение «Hello», все разделено? Что это дает? Что ж, Nest JS предлагает несколько уровней, что приводит к независимой структуре на каждом уровне, что делает ваше приложение тестируемым, открытым для расширения и дает вам возможность заменить любой из слоев с минимальными усилиями.

Теперь, когда мы создали наше первое приложение с помощью интерфейса командной строки Nest, мы готовы запустить наше приложение, если оно еще не запущено, используйте следующую команду в командной строке: nest start.

Понимание жизненного цикла Nest JS

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

Чтобы закончить эту статью, мы могли бы начать просмотр вывода этого приложения с помощью браузера или любого инструмента тестирования API, такого как Postman, который является отличным инструментом для тестирования API, предоставляя удобный интерфейс для отправки запросов и наблюдения за ответами.

Мы можем легко настроить Postman для выполнения запросов к нашему приложению Nest JS, гарантируя, что наши конечные точки работают должным образом. Теперь откройте Postman и создайте новый запрос, затем введите URL-адрес http://localhost:3000/ (3000 — это номер порта, который мы настроили ранее) и выберите метод HTTP как GET. Нажмите кнопку «Отправить», и вы должны увидеть ответ «Hello World!». в теле ответа.

Примечание. Вы можете просто просмотреть те же результаты, открыв тот же URL-адрес из браузера.

Поздравляем! Вы успешно запустили свое первое приложение Nest JS и протестировали конечную точку с помощью Postman.

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

Моя учетная запись LinkedIn:

Свяжитесь со мной для любой помощи, предложения, или даже сказать привет! 😎