Главная » Хабрахабр » NestJS - тот самый, настоящий бэкенд на nodejs

NestJS - тот самый, настоящий бэкенд на nodejs

image

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

Все упаковано в простой и легкой форме, так что выбор за вами - решаете ли вы использовать всю платформу или просто использовать ее компоненты.
Для начала расскажу про свой опыт. Поэтому, NestJS- это не только фреимворк для бэкенда, но и возможность войти в мир передовых концепции, например таких как DDD, Event sourcing и микросервисной архитектуре. NET, далее был фронтенд на AngularJS. Долгое время писал на ASP. И вот оно! В октябре 2016 года был переход на Angular и Typescript. До этого (разработки на nestjs) на node разрабатывал лишь исключительно ради забавы, и как-то даже была попытка внести хорошие практики и typescript в популярный Koa. Типизация во фронтенде, можно делать сложные вещи достаточно легко! Но NestJS это все таки немного другое.

NestJS, фреймворк, который полностью написан на TypeScript (он также поддерживает JS, но типы уж очень хороши), он легко тестируется и содержит все необходимое.

Как создать простое приложение на NestJS?

Любые расширения для express, легко внедрить в Nest. У NestJS под капотом крутится express. Но это тут не главное, при большом желании express можно взять и поменять.

Для начала можно скопировать к себе небольшой стартовый набор:

git clone https://github.com/nestjs/typescript-starter.git project

В server.ts включена асинхронная функция, которая отвечает за загрузку нашего приложения:

import from '@nestjs/core';
import { ApplicationModule } from './modules/app.module'; async function bootstrap() { const app = await NestFactory.create(ApplicationModule); await app.listen(3000);
}
bootstrap();

Ну и далее запустить npm run start и увидеть на порту 3000 приложение.

Из чего же состоит NestJS?

Автор фреимворка был вдохновлен идеями Angular, и NestJS получился ну очень похожим на Angular, особенно в ранних версиях.

Controllers

Простой пример контроллера: Cлой контроллеров отвечает за обработку входящих запросов и возврат ответа клиенту.

import { Controller, Get } from '@nestjs/common'; @Controller('cats')
export class CatsController { @Get() findAll() { return []; }
}

Providers

Они могут быть внедрены в контроллеры и другие провайдеры. Почти все является Providers — Service, Repository, Factory, Helper и т.д. Если сказать языком Angular — то это все `@Injectables

Например обычный service:

import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface'; @Injectable()
export class CatsService { private readonly cats: Cat[] = []; create(cat: Cat) { this.cats.push(cat); } findAll(): Cat[] { return this.cats; }
}

Modules

Декоратор Module() предоставляет метаданные, которые Nest использует для организации структуры приложения. Модуль - это класс с декоратором Module(). Корневой модуль - это место, где Nest начинает упорядочивать дерево приложений. Каждое приложение Nest имеет как минимум один модуль, корневой модуль. В большинстве случаев у вас будет несколько модулей, каждый из которых имеет тесно связанный набор возможностей. Фактически, корневой модуль может быть единственным модулем в вашем приложении, особенно когда приложение маленькое, но это не имеет смысла. В Nest модули по умолчанию являются синглетонами, поэтому вы можете без труда делить один и тот же экземпляр компонента между двумя и более модулями.

import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service'; @Module({ controllers: [CatsController], components: [CatsService],
})
export class CatsModule {}

Немного про динамические модули

Это позволяет создавать настраиваемые модули без каких-либо усилий. Модульная система Nest поставляется с функцией динамических модулей. Давайте посмотрим на DatabaseModule:

import { Module, DynamicModule } from '@nestjs/common';
import { createDatabaseProviders } from './database.providers';
import { Connection } from './connection.component'; @Module({ components: [Connection],
})
export class DatabaseModule { static forRoot(entities = [], options?): DynamicModule { const providers = createDatabaseProviders(options, entities); return { module: DatabaseModule, components: providers, exports: providers, }; }
}

Он определяет компонент Connection по умолчанию, но дополнительно - в зависимости от переданных опций и сущностей - создает коллекцию поставщиков, например, компонентов репозитория. По факту динамический модуль расширяет метаданные модуля. Эта существенная функция полезна, когда вам нужно динамически регистрировать компоненты. Затем вы можете импортировать DatabaseModule следующим образом:

import { Module } from '@nestjs/common';
import { DatabaseModule } from './database/database.module';
import { User } from './users/entities/user.entity'; @Module({ imports: [ DatabaseModule.forRoot([User]), ],
})
export class ApplicationModule {}

Кстати, для работы с базой есть крутой TypeORM, умеющий работать с большинством баз данных.

Middlewares

Они имеют доступ к request и response. Middlewares - это функция, которая вызывается перед обработчиком роута. По сути они являются такими же как и в express.

import { Injectable, NestMiddleware, MiddlewareFunction } from '@nestjs/common'; @Injectable()
export class LoggerMiddleware implements NestMiddleware { resolve(...args: any[]): MiddlewareFunction { return (req, res, next) => { console.log('Request...'); next(); }; }
}

Exception Filters

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

Каждое исключение обрабатывается глобальным фильтром исключений, и когда оно не распознается (не HttpException или класс, который наследует HttpException), пользователь получает следующий ответ JSON:

{ "statusCode": 500, "message": "Internal server error"
}

Pipes

Pipe должен реализовывать интерфейс PipeTransform.

import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common'; @Injectable()
export class ValidationPipe implements PipeTransform { transform(value: any, metadata: ArgumentMetadata) { return value; }
}

Pipe преобразует входные данные в желаемый результат.

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

@Post()
@UsePipes(new ValidationPipe(createCatSchema))
async create(@Body() createCatDto: CreateCatDto) { this.catsService.create(createCatDto);
}

Или же можно обьявить глобальный pipe:

async function bootstrap() { const app = await NestFactory.create(ApplicationModule); app.useGlobalPipes(new ValidationPipe()); await app.listen(3000);
}
bootstrap();

Guards

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

@Injectable()
export class RolesGuard implements CanActivate { canActivate( context: ExecutionContext, ): boolean | Promise<boolean> | Observable<boolean> { // const request = context.switchToHttp().getRequest(); // const data = context.switchToWs().getData(); return true; }
}
Использование: <source lang="javascript">
@Controller('cats')
@UseGuards(RolesGuard)
export class CatsController {}

Interceptors

Они позволяют: Перехватчики имеют ряд полезных возможностей, которые вдохновлены техникой Aspect-Oriented Programming (AOP).

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

Микросервисы

Микросервис Nest - это просто приложение, которое использует другой транспортный уровень (не HTTP).

Nest поддерживает два типа связи - TCP и Redis pub/sub, но новую транспортную стратегию легко внедрить, реализовав интерфейс CustomTransportStrategy.

Вы легко можете создать микросервис из своего приложения:

import { NestFactory } from '@nestjs/core';
import { ApplicationModule } from './modules/app.module';
import { Transport } from '@nestjs/microservices'; async function bootstrap() { const app = await NestFactory.createMicroservice(ApplicationModule, { transport: Transport.TCP, }); app.listen(() => console.log('Microservice is listening'));
}
bootstrap();

Микросервис Nest распознает сообщения по шаблонам. Шаблон представляет собой простое значение, объект, строку или даже число.

import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices'; @Controller()
export class MathController { @MessagePattern({ cmd: 'sum' }) sum(data: number[]): number { return (data || []).reduce((a, b) => a + b); }
}

А для общения между микросервисами необходимо использовать клиент:

@Client({ transport: Transport.TCP, port: 5667 })
client: ClientProxy;

А вот так будет выглядеть отправка сообщения:

@Get()
call(): Observable<number> { const pattern = { cmd: 'sum' }; const data = [1, 2, 3, 4, 5]; return this.client.send<number>(pattern, data);
}

NestJS и Angular так сильно вместе связаны, что автора фреймворка можно легко встретить на ng конференциях и митапах. Например, недавно команда nrwl включила в свой nx шаблон nestjs.

ng g node-app nestjs-app -framework nestjs

NestJS уже достаточно зрел, и многие компании уже используют его.
Кто сейчас использует NestJS в продакшне?

Сам фреймворк: https://github.com/nestjs/nest

Много крутых ссылок по теме здесь:Awesome-nestjs
Русскоязычное сообщество NestJS в телеграмме https://t.me/nest_ru
Русскоязычный доклад про NestJS.

Ну и конечно подписывайтесь на канал https://t.me/ngFanatic где есть новости про NestJS и Angular.

S.: Это только часть возможностей NestJS, про личный опыт, длиною в год, будет отдельная статья. P.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

[Из песочницы] ВИЧ – методы лечения от первых лекарств до сегодняшнего дня

Прежде, чем приступить к изложению материала, хотелось бы сказать несколько слов о себе: участник сообществ по борьбе с отрицанием ВИЧ („ВИЧ/СПИД диссидентством“): в 2016-2018 годах „ВИЧ/СПИД диссиденты и их дети“, с 2018 года – „ВИЧ/СПИД отрицание и альтернативная медицина“. Это ...

Изюминки прошедшей Moscow Python Conf++ 2019: трансформация в площадку для общения

Самыми горячими темами Moscow Python Conf++ оказались асинхронная разработка, а также сопоставление Python, его лучших практик и инструментария с аналогами из других языков, и его место в ландшафте современной разработки. Плюс мы пригласили выступить Бенджамина Петерсона, одного из разработчиков CPython, ...