Nest.js от нуля до одной серии (1): создание проекта, настройки маршрутизации и модули

Node.js

предисловие

Эта серия будет написана с точки зрения фронтенда и будет делиться моим собственным опытом выхода на яму. Учебное пособие предназначено в основном для читателей, имеющих опыт работы с интерфейсом или не имеющих опыта работы с ним, но, конечно, если вы хотите попробовать Node.js, знатоки серверной части также приветствуются.

Nest — это платформа для создания эффективных, масштабируемых серверных приложений Node.js. Он использует прогрессивный JavaScript, имеет встроенную и полную поддержку TypeScript (но при этом позволяет разработчикам писать код на чистом JavaScript) и сочетает в себе элементы ООП (объектно-ориентированного программирования), FP (функционального программирования) и FRP (функционально-реактивного программирования).

Под капотом Nest использует мощные платформы HTTP-серверов, такие как Express (по умолчанию) и Fastify. Nest обеспечивает уровень абстракции поверх этих фреймворков, а также предоставляет свой API напрямую разработчикам. Это упрощает использование бесчисленных сторонних модулей для каждой платформы.

Nest — это back-end фреймворк, с которым я общался последние полгода. Раньше я использовал Koa2, но так как старый проект был написан в беспорядке «старшим» фронтендом, я выбрал этот на основе машинописного текста. , недавно появившийся в Китае. Фреймворк подвергся рефакторингу. На данный момент у nestjs на Github 25,2 тысячи звезд, а основные пользователи находятся за границей, так что сторона может доказать свою определенную стабильность.

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

Адрес проекта GitHub, Добро пожаловать в Звезду больших парней.

Хорошо, давайте остановимся здесь, давайте начнем:

1. Создание проекта

Окружение проекта:

  • node.js: 11.13.0+
  • npm: 6.13.4+
  • nestjs: 7.0.3
  • typescript: 3.8.3

Убедитесь, что Node.js (>= 10.13.0) установлен в операционной системе, затем установите Nest.js, затем создайте новый проект и введите следующие команды:

$ npm i -g @nestjs/cli
$ nest new project-name

После того, как ввод будет завершен, он будет инициализирован.В это время вам будет задан вопрос, какой метод использовать для управления пакетом зависимостей:

я выбираюyarn, в основном отечественныеnpmЗагрузка идет медленно. если нетyarnДа, вы можете скачать его или использоватьnpm, но в этой серии руководств используетсяyarn.

Когда курица закончила клювать рис, когда собака закончила облизывать лапшу, и когда огонь сломал замок, вы получите следующее сообщение:

Согласно подсказке войдите в проект, не случайно каталог должен выглядеть так:

бегатьyarn run startилиyarn start, вы увидите, что консоль выводит следующую информацию, указывающую, что служба запущена:

2. Привет, мир!

1. Маршрут указывает на

Открытымsrcвнизmain.ts, неудивительно, что вы должны увидеть следующий код:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

await NestFactory.create(AppModule);Указывает, что AppModule создан с использованием фабричной функции Nest, а модуль будет представлен позже.

await app.listen(3000)Указывает, что порт прослушивания — 3000, который можно настроить. Если порт 3000 занят и проект не запускается, его можно изменить на другой порт.

Затем мы получаем доступ к локальному порту 3000 через Postman и находим следующую информацию:

Тогда все, что нам нужно сделать, это выяснить, почемуHello World!причина.

Открытымsrcвнизapp.service.ts, вы увидите следующий код:

// src/app.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

Нашел способ здесьgetHello(), вернулсяHello World!строка, так где она называется?

Открытымsrcвнизapp.controller.ts:

// src/app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

О, так оно и есть, вот введениеapp.service.tsсерединаAppServiceкласс и создайте его экземпляр, затем передайте@Get()ретушьAppControllerвнутреннийgetHello()метод, указывающий, что этот метод будетGETзаявка на звонок.

Изменим маршрутизацию, то есть в@Get()Запишите строку внутри круглых скобок:

// src/app.controller.ts
@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get('hello-world')
  getHello(): string {
    return this.appService.getHello();
  }
}

потомперезапустить проект(Нажмите Ctrl + C на консоли, чтобы завершить проект, затем введитеyarn start), то мы посещаем сноваlocalhost:3000/, ты найдешь404в настоящее время:

В этот момент мы входимlocalhost:3000/hello-world, появляются знакомые персонажи:

Это маршрут Nest, не так ли просто?

2. Локальный префикс маршрутизации

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

все ещеapp.controller.ts,существует@Controller()написатьlesson-1, что обозначаеттекущий файл, все маршруты имеют префиксlesson-1:

// src/app.controller.ts
@Controller('lesson-1')
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get('hello-world')
  getHello(): string {
    return this.appService.getHello();
  }
}

Перезапускаем проект, в это время посещаемlocalhost:3000/lesson-1/hello-world, укажет наgetHello()метод:

3. Глобальный префикс маршрутизации

Это проще, просто нужноmain.tsплюсapp.setGlobalPrefix():

// src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.setGlobalPrefix('nest-zero-to-one'); // 全局路由前缀
  await app.listen(3000);
}
bootstrap();

После этого, пока услуга запрашивается, все маршруты должны быть добавленыnest-zero-to-oneПрефикс:

4. Запустите проект в режиме nodemon

Если вы не хотите часто перезагружаться, вы можете использоватьyarn start:devЗапустите проект, он будет использовать nodemon для отслеживания изменений файлов и автоматического перезапуска службы.

Если появится следующее сообщение:

Причина в том, что он мог быть установлен раньшеtypescriptилиnestjsЛеса, а затем при создании нового проекта,typescriptВерсия относительно старая, просто обновитесь до3.7.0выше:

$ yarn add typescript -D

Появляется этот снимок экрана, но нет информации о маршрутизации, что указывает на необходимость изменения конфигурации nodemon:

package.json:
❌ "start:dev": "concurrently --handle-input \"wait-on dist/main.js && nodemon\" \"tsc -w -p tsconfig.build.json\" ",    
✅ "start:dev": "concurrently --handle-input \"wait-on dist/src/main.js && nodemon\" \"tsc -w -p tsconfig.build.json\" ",

nodemon.json:
❌ "exec": "node dist/main"  
✅ "exec": "node dist/src/main"

а затем запуститьyarn start:devПросто хорошо:

Или проще говоряmain.tsБросьте его в корневой каталог (тот же уровень, что и src)

Таким образом, любые изменения в файле автоматически перезапустят службу.

3. Новые модули

Благодаря вышеизложенному вы должны быть знакомы с шаблонами проектирования NestJS, в основномController,Service,ModuleРаботая вместе, формируется модуль.

  • Controller: Контроллер в традиционном смысле, предоставляющий API-интерфейс, отвечающий за обработку некоторых простых сервисов, таких как маршрутизация, передача и проверка;
  • Service:Также известен какProvider, — это общий термин для ряда сервисов, репозиториев, фабричных методов и помощников, которые в основном отвечают за обработку конкретных операций, таких как добавление, удаление, изменение базы данных, запросы, транзакции, параллелизм и другие логические коды;
  • Module: ответственный заControllerиServiceсвязанный, похожий наnamespaceКонцепция чего-либо;

Очень интуитивно понятная традиционная структура MVC, бэкэнд с опытом разработки Spring не должен быть незнакомым.

Сделаем это, добавив модуль User:

1. Service

Лично принято сначала создавать Службу, а затем создавать Модуль в последнюю очередь, потому что и Контроллер, и Модуль должны импортировать Службу, чтобы при импорте была подсказка (конечно, вы также можете заранее написать оператор импорта , но проверка ESLint покажет красное пятно, обсессивно-компульсивное расстройство. Пациент выразил неодобрение).

Воспользуйтесь инструкциями, предоставленными утилитой Nest-Cli, для быстрого создания файлов. Синтаксис выглядит следующим образом:

$ nest g [文件类型] [文件名] [文件目录(src目录下)]

Мы входим:

$ nest g service user logical

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

На user.service.spec.ts на картинке выше можно не обращать внимания... По крайней мере, я его писал больше полугода, и не трогал такого рода файл.

Затем мы смотрим наuser.service.ts, файлы, созданные с помощью этой команды, в основном выглядят так:

// src/logical/user/user.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class UserService {}

Итак, мы можем сымитировать app.service.ts, чтобы написать простой бизнес:

// src/logical/user/user.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class UserService {
    findOne(username: string): string {
    if (username === 'Kid') {
      return 'Kid is here';
    }
    return 'No one here';
  }
}

2. Controller

Теперь напишем контроллер, вводим следующие команды:

$ nest g controller user logical

Инициализированный контроллер в основном выглядит так:

// src/logical/user/user.controller.ts
import { Controller } from '@nestjs/common';

@Controller('user')
export class UserController {}

Далее мы вводим бизнес-логику Сервиса:

import { Controller, Post, Body } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private readonly usersService: UserService) {}

  @Post('find-one')
  findOne(@Body() body: any) {
    return this.usersService.findOne(body.username);
  }
}

Его необходимо создать с помощью конструктора, прежде чем можно будет вызвать метод, который используется здесь.POSTполучать запросы через@Body()получить параметры тела запроса (request.body).

Давайте проверим это с помощью Postman, сначала введите имя пользователя по желанию:

Затем перейдите в «Малыш»:

Видно, что мы удачно сопоставили маршрут, и написанное дело вступило в силу.

На данный момент выполнено 70% процесса, в дальнейшем развитие бизнеса (перевозка кирпичей) в основном подбрасывает Сервис и Контроллера. . .

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

3. Module

Это то, что связывает Сервис и Контроллер.Многие удивятся.Выше только создали Сервис и Контроллер.Как к ним можно получить доступ?

Откройте app.module.ts:

// src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserService } from './logical/user/user.service';
import { UserController } from './logical/user/user.controller';

@Module({
  imports: [],
  controllers: [AppController, UserController],
  providers: [AppService, UserService],
})
export class AppModule {}

Обнаружено, что при использовании команды для создания файла он автоматически ввел для нас файлы, относящиеся к Пользователю, а в файле main.ts он уже был введен.AppModuleи использоватьNestFactoryЭкземпляр создан.

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

Но в качестве учебника, давайте поговорим об этом примерно, сначала создайте файл:

$ nest g module user logical

Инициализированный модуль в основном выглядит так:

import { Module } from '@nestjs/common';

@Module({})
export class UserModule {}

Собираем Сервис и Контроллер:

import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';

@Module({
  controllers: [UserController],
  providers: [UserService],
  exports: [UserService],
})
export class UserModule {}

В чем преимущество этого, то есть, когда другие модули хотят ввести пользователя, нет необходимости вводить одновременно Сервис и Контроллер, давайте модифицируем егоapp.module.ts:

// src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
// import { UserService } from './logical/user/user.service';
// import { UserController } from './logical/user/user.controller';
import { UserModule } from './logical/user/user.module';

@Module({
  imports: [UserModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Сохраните и запустите, и обнаружите, что маршрут все еще действует:

Конечно, в модуле есть и другой продвинутый геймплей, который здесь не будет раскрываться.

Суммировать

В этой статье рассказывается о создании проекта Nest.js, маршрутизации доступа и добавлении новых модулей.

Каждый модуль можно разделить на Сервис, Контроллер, Модуль. В этой записи в блоге: Сервис отвечает за логику обработки, Контроллер отвечает за маршрутизацию, Модуль отвечает за интеграцию.

Из реального боя видно, что Nest относительно прост, и единственным препятствием может быть TypeScript.

Люди, привыкшие писать на JavaScript, возможно, не смогут адаптироваться к такому типу проверки, особенно те, кто увлекается различными операциями, но, поскольку речь идет о бэкэнд-поле, лучше быть более строгим, и различные неровности можно избежать на ранней стадии ямы.

В следующей статье будет описано, как подключиться к базе данных MySQL.

Эта статья записана вПрактическое руководство по NestJS, следите за новыми статьями.

`