NestJS es un marco diseñado para facilitar la vida de un desarrollador, utilizando los enfoques arquitectónicos correctos y dictando sus propias reglas.
Por lo tanto, NestJS no es solo un marco de back-end, sino también la oportunidad de ingresar al mundo de los conceptos avanzados, como
DDD ,
abastecimiento de eventos y arquitectura de microservicios. Todo está empaquetado de una manera simple y fácil, por lo que la elección es suya, ya sea que decida usar toda la plataforma o simplemente usar sus componentes.
Primero, te contaré sobre mi experiencia. Durante mucho tiempo escribí en ASP.NET, luego hubo una interfaz en AngularJS. En octubre de 2016, hubo un cambio a angular y mecanografiado. ¡Y aquí está! Al escribir en la interfaz, puede hacer cosas complejas con bastante facilidad. Antes de esto (desarrollo en nestjs) en el nodo, lo desarrollé solo por diversión, y de alguna manera incluso hubo un
intento de introducir buenas prácticas y mecanografía en el popular Koa . Pero NestJS sigue siendo un poco diferente.
NestJS, un marco que está completamente escrito en TypeScript (también es compatible con JS, pero los tipos son muy buenos), es fácil de probar y contiene todo lo que necesita.
¿Cómo crear una aplicación simple en NestJS?NestJS tiene expreso debajo del capó. Cualquier extensión para express es fácil de implementar en Nest. Pero este no es el punto aquí, con un fuerte deseo expreso se puede tomar y cambiar.
Primero, puede copiar un pequeño kit de inicio para usted:
git clone https://github.com/nestjs/typescript-starter.git project
Server.ts incluye una función asincrónica que se encarga de cargar nuestra aplicación:
import { NestFactory } from '@nestjs/core'; import { ApplicationModule } from './modules/app.module'; async function bootstrap() { const app = await NestFactory.create(ApplicationModule); await app.listen(3000); } bootstrap();
Bueno, entonces inicie npm run start y vea la aplicación en el puerto 3000.
¿De qué está hecho NestJS?El autor del marco se inspiró en las ideas de Angular, y NestJS resultó ser muy similar a Angular, especialmente en versiones anteriores.
ControladoresLa capa de controlador es responsable de procesar las solicitudes entrantes y devolver una respuesta al cliente. Un ejemplo simple de controlador:
import { Controller, Get } from '@nestjs/common'; @Controller('cats') export class CatsController { @Get() findAll() { return []; } }
ProveedoresCasi todo son proveedores: servicio, repositorio, fábrica, ayudante, etc. Se pueden implementar en controladores y otros proveedores. Si dices el idioma de Angular, todo es `@Injectables
Por ejemplo, un servicio regular:
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; } }
MódulosUn módulo es una clase con el decorador
Module (). El decorador
Module () proporciona metadatos que Nest usa para organizar la estructura de la aplicación. Cada aplicación Nest tiene al menos un módulo, el módulo raíz. El módulo raíz es donde Nest comienza a organizar el árbol de aplicaciones. De hecho, el módulo raíz puede ser el único módulo en su aplicación, especialmente cuando la aplicación es pequeña, pero eso no tiene sentido. En la mayoría de los casos, tendrá varios módulos, cada uno de los cuales tiene un conjunto de características estrechamente relacionadas. En Nest, los módulos son singleton de forma predeterminada, por lo que puede compartir fácilmente la misma instancia de componente entre dos o más módulos.
import { Module } from '@nestjs/common'; import { CatsController } from './cats.controller'; import { CatsService } from './cats.service'; @Module({ controllers: [CatsController], components: [CatsService], }) export class CatsModule {}
Un poco sobre módulos dinámicosEl sistema modular Nest viene con función de módulo dinámico. Esto le permite crear módulos personalizados sin ningún esfuerzo. Echemos un vistazo a 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, }; } }
Define el componente de conexión de forma predeterminada, pero adicionalmente, dependiendo de las opciones y entidades transferidas, crea una colección de proveedores, por ejemplo, componentes de repositorio. De hecho, el módulo dinámico expande los metadatos del módulo. Esta característica esencial es útil cuando necesita registrar componentes dinámicamente. Luego puede importar el DatabaseModule de la siguiente manera:
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 {}
Por cierto, para trabajar con la base de datos hay un
TypeORM genial que puede funcionar con la mayoría de las bases de datos.
MiddlewaresMiddlewares es una función que se llama antes del controlador de ruta. Tienen acceso a solicitud y respuesta. De hecho, son lo mismo que en
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(); }; } }
Filtros de excepciónNest tiene una capa de excepción, que es responsable de detectar las excepciones no controladas y devolver la respuesta adecuada al usuario final.
Cada excepción es manejada por el filtro de excepción global, y cuando no se reconoce (no es una HttpException o una clase que hereda una HttpException), el usuario recibe la siguiente respuesta JSON:
{ "statusCode": 500, "message": "Internal server error" }
TubosLa tubería debe implementar la interfaz PipeTransform.
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common'; @Injectable() export class ValidationPipe implements PipeTransform { transform(value: any, metadata: ArgumentMetadata) { return value; } }
La tubería convierte la entrada al resultado deseado.
Además, esto puede pasar para la validación, ya que también es posible que arrojen una excepción si los datos son incorrectos. Por ejemplo:
@Post() @UsePipes(new ValidationPipe(createCatSchema)) async create(@Body() createCatDto: CreateCatDto) { this.catsService.create(createCatDto); }
O puede declarar una tubería global:
async function bootstrap() { const app = await NestFactory.create(ApplicationModule); app.useGlobalPipes(new ValidationPipe()); await app.listen(3000); } bootstrap();
GuardiasLos guardias deben implementar la interfaz CanActivate. Los guardias tienen la responsabilidad exclusiva. Determinan si la solicitud debe ser procesada por el controlador de ruta o no.
@Injectable() export class RolesGuard implements CanActivate { canActivate( context: ExecutionContext, ): boolean | Promise<boolean> | Observable<boolean> {
InterceptoresLos interceptores tienen algunas características útiles que están inspiradas en la técnica de Programación Orientada a Aspectos (AOP). Te permiten:
- enlazar lógica adicional antes / después de ejecutar el método;
- convierte el resultado devuelto por la función;
- Convertir una excepción lanzada desde una función
- redefinir completamente la función en función de las condiciones seleccionadas (por ejemplo, para el almacenamiento en caché).
MicroserviciosNest Microservice es solo una aplicación que usa una capa de transporte diferente (no HTTP).
Nest admite dos tipos de comunicación: TCP y Redis pub / sub, pero la nueva estrategia de transporte es fácil de implementar mediante la implementación de la interfaz CustomTransportStrategy.
Puede crear fácilmente un microservicio desde su aplicación:
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 Microservice reconoce los mensajes por patrones. Un patrón es un valor simple, un objeto, una cadena o incluso un número.
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); } }
Y para la comunicación entre microservicios, debe usar el cliente:
@Client({ transport: Transport.TCP, port: 5667 }) client: ClientProxy;
Y aquí estará el envío del mensaje:
@Get() call(): Observable<number> { const pattern = { cmd: 'sum' }; const data = [1, 2, 3, 4, 5]; return this.client.send<number>(pattern, data); }
NestJS y Angular están tan estrechamente conectados que el autor del marco puede verse fácilmente en conferencias y reuniones. Por ejemplo, el equipo nrwl recientemente
incluyó la plantilla nestjs en su nx.
ng g node-app nestjs-app -framework nestjs
NestJS ya es lo suficientemente maduro, y muchas compañías ya lo están utilizando.
¿Quién está usando NestJS en producción en este momento?El marco en sí:
https://github.com/nestjs/nestMuchos enlaces
relacionados interesantes aquí:
Awesome-nestjsComunidad de habla rusa de NestJS en un telegrama
https://t.me/nest_ruInforme en ruso sobre NestJS.Y, por supuesto, suscríbase al canal en el telegrama
@ngFanatic donde hay noticias sobre NestJS y Angular.
PD: Esto es solo una parte de las capacidades de NestJS, sobre una experiencia personal de un año, habrá un artículo separado.