NestJS - das gleiche, echte Backend auf NodeJS

    Bild

    NestJS ist das Framework, das dem Entwickler das Leben erleichtern soll, indem es die richtigen Architekturansätze verwendet und seine eigenen Regeln diktiert.

    Daher ist NestJS nicht nur ein Backend-Framework, sondern auch die Möglichkeit, in die Welt fortschrittlicher Konzepte wie DDD , Event-Sourcing und Microservice-Architektur einzusteigen . Alles ist auf einfache und einfache Weise verpackt. Sie haben also die Wahl, ob Sie die gesamte Plattform oder nur deren Komponenten verwenden möchten.

    Zunächst erzähle ich Ihnen von meinen Erfahrungen. Lange habe ich über ASP.NET geschrieben, dann gab es ein Frontend für AngularJS. Im Oktober 2016 wurde auf Angular und Typescript umgestellt. Und hier ist es! Wenn Sie im Frontend tippen, können Sie ganz einfach komplexe Dinge erledigen! Vor dieser (Entwicklung auf nestjs) auf node habe ich sie nur zum Spaß entwickelt, und irgendwie gab es sogar den Versuch, gute Praktiken und Typoskripte in das beliebte Koa einzuführen . Aber NestJS ist noch ein bisschen anders.

    NestJS, ein Framework, das vollständig in TypeScript geschrieben ist (es unterstützt auch JS, aber die Typen sind sehr gut), ist einfach zu testen und enthält alles, was Sie brauchen.

    Wie erstelle ich eine einfache Anwendung auf NestJS?

    NestJS hat Express unter der Haube. Alle Express-Erweiterungen sind in Nest einfach zu implementieren. Aber das ist hier nicht der Punkt, mit dem ein starker Wunsch ausgedrückt und geändert werden kann.

    Zuerst können Sie sich ein kleines Starter-Kit kopieren:

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

    Server.ts enthält eine asynchrone Funktion, die für das Laden unserer Anwendung verantwortlich ist:

    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();
    

    Nun, dann starte npm run start und sieh dir die Anwendung auf Port 3000 an.

    Woraus besteht NestJS?

    Der Autor des Frameworks ließ sich von Angulars Ideen inspirieren, und NestJS war Angular sehr ähnlich, insbesondere in früheren Versionen.

    Controller

    Die Controllerschicht ist für die Verarbeitung eingehender Anforderungen und die Rückgabe einer Antwort an den Client verantwortlich. Ein einfaches Steuerungsbeispiel:

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

    Anbieter

    Fast alles ist Anbieter - Service, Repository, Fabrik, Helfer usw. Sie können in Steuerungen und anderen Anbietern implementiert werden. Wenn Sie die Sprache von Angular sagen - es ist alles "@Injectables".

    Zum Beispiel ein regulärer 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;
      }
    }
    

    Module

    Ein Modul ist eine Klasse mit dem Dekorator Module (). Der Module () -Dekorator stellt Metadaten bereit, mit denen Nest die Struktur der Anwendung organisiert. Jede Nest-Anwendung verfügt über mindestens ein Modul, das Root-Modul. Im Stammmodul beginnt Nest, den Anwendungsbaum zu organisieren. Tatsächlich ist das Stammmodul möglicherweise das einzige Modul in Ihrer Anwendung, insbesondere wenn die Anwendung klein ist, aber es macht keinen Sinn. In den meisten Fällen verfügen Sie über mehrere Module, von denen jedes einen eng verwandten Funktionsumfang aufweist. In Nest sind Module standardmäßig Singleton, sodass Sie dieselbe Komponenteninstanz problemlos für zwei oder mehr Module freigeben können.

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

    Ein wenig über dynamische Module

    Das Nest-Modulsystem verfügt über eine dynamische Modulfunktion. Auf diese Weise können Sie mühelos benutzerdefinierte Module erstellen. Werfen wir einen Blick auf das 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,
        };
      }
    }
    

    Standardmäßig wird die Verbindungskomponente definiert. Zusätzlich wird - abhängig von den übertragenen Optionen und Entitäten - eine Sammlung von Anbietern erstellt, z. B. Repository-Komponenten. Tatsächlich erweitert das dynamische Modul die Metadaten des Moduls. Diese wichtige Funktion ist nützlich, wenn Sie Komponenten dynamisch registrieren müssen. Dann können Sie das DatabaseModule wie folgt importieren:

    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 {}
    

    Übrigens, für die Arbeit mit der Datenbank gibt es einen coolen TypeORM , der mit den meisten Datenbanken funktionieren kann.

    Middlewares

    Middlewares ist eine Funktion, die vor dem Route Handler aufgerufen wird. Sie haben Zugriff auf Anforderung und Antwort. In der Tat sind sie die gleichen wie im 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();
        };
      }
    }
    

    Ausnahmefilter

    Nest verfügt über eine Ausnahmeschicht, die für das Abfangen nicht behandelter Ausnahmen und das Zurückgeben der entsprechenden Antwort an den Endbenutzer verantwortlich ist.

    Jede Ausnahme wird vom globalen Ausnahmefilter behandelt. Wenn sie nicht erkannt wird (keine HttpException oder Klasse, die eine HttpException erbt), erhält der Benutzer die folgende JSON-Antwort:

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

    Pipes

    Pipe muss die PipeTransform-Schnittstelle implementieren.
    import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';
    @Injectable()
    export class ValidationPipe implements PipeTransform {
      transform(value: any, metadata: ArgumentMetadata) {
        return value;
      }
    }
    

    Pipe wandelt die Eingabe in das gewünschte Ergebnis um.

    Darüber hinaus kann dies zur Validierung durchlaufen werden, da sie auch eine Ausnahme auslösen können, wenn die Daten falsch sind. Zum Beispiel:

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

    Oder Sie können eine globale Pipe deklarieren:

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

    Guards

    Guards müssen die CanActivate-Schnittstelle implementieren. Die Wachen tragen die alleinige Verantwortung. Sie legen fest, ob die Anforderung vom Routenhandler verarbeitet werden soll oder nicht.

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

    Interceptors

    Interceptors verfügen über eine Reihe nützlicher Funktionen, die von aspektorientierter Programmierung (AOP) inspiriert sind. Sie ermöglichen es Ihnen:

    • zusätzliche Logik binden, bevor / nachdem die Methode ausgeführt wird;
    • konvertiert das von der Funktion zurückgegebene Ergebnis;
    • Konvertiert eine von einer Funktion ausgelöste Ausnahme
    • Definieren Sie die Funktion in Abhängigkeit von den ausgewählten Bedingungen (z. B. für das Caching) vollständig neu.

    Microservices

    Nest Microservices ist nur eine Anwendung, die eine andere Transportschicht verwendet (nicht HTTP).

    Nest unterstützt zwei Arten der Kommunikation - TCP und Redis Pub / Sub. Die neue Transportstrategie lässt sich jedoch durch Implementierung der CustomTransportStrategy-Schnittstelle leicht implementieren.

    Sie können ganz einfach einen Microservice aus Ihrer Anwendung erstellen:

    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 erkennt Nachrichten anhand von Mustern. Ein Muster ist ein einfacher Wert, ein Objekt, eine Zeichenfolge oder sogar eine Zahl.

    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);
      }
    }
    

    Und für die Kommunikation zwischen Microservices müssen Sie den Client verwenden:

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

    Und hier wird die Nachricht gesendet:

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

    NestJS und Angular sind so eng miteinander verbunden, dass der Autor des Frameworks bei Konferenzen und Meetings leicht zu sehen ist. Zum Beispiel hat das nrwl-Team kürzlich die nestjs-Vorlage in sein nx aufgenommen.

    ng g node-app nestjs-app -framework nestjs

    NestJS ist bereits ausgereift und wird von vielen Unternehmen bereits eingesetzt.
    Wer setzt NestJS gerade in der Produktion ein?

    Das Framework selbst: https://github.com/nestjs/nest

    Viele coole Links zum Thema hier: Awesome-nestjs
    russischsprachige Community von NestJS in einem Telegramm https://t.me/nest_en
    russischsprachiger Bericht über NestJS.

    Und abonnieren Sie natürlich den Kanal im @ngFanatic- Telegramm, in dem es Neuigkeiten über NestJS und Angular gibt.

    PS: Dies ist nur ein Teil der Möglichkeiten von NestJS, über eine einjährige persönliche Erfahrung wird es einen eigenen Artikel geben.

    Jetzt auch beliebt: