Was ist NestJS?
NestJS ist ein modernes NodeJS-Framework, das beliebte NodeJS-Frameworks wie Express und Fastify im Hintergrund nutzt. NestJS wurde weitgehend von Angular inspiriert und verwendet daher ein Modulsystem im Angular-Stil. NestJS ist in TypeScript geschrieben, unterstützt aber auch natives JavaScript.
Voraussetzungen
Um diesem Tutorial zu folgen, müssen Sie die folgenden Anforderungen erfüllen
- Kompetenz in PostMan oder einem anderen API-Testtool.
- Grundkenntnisse von NodeJS und Express-Apps.
- Grundkenntnisse von TypeScript.
- Kompetenz in MongoDB (Mongoose).
Folgendes sollte auf Ihrem System installiert sein
- NodeJS v.14 und höher.
- Visual Studio Code (empfohlen) oder jede andere IDE.
- PostMan oder ein anderes API-Testtool.
Gemeinsame Terminologien, die in NestJS verwendet werden;
Hier sind einige der am häufigsten verwendeten Begriffe in NestJS, denen Sie in diesem Artikel häufig begegnen werden.
Schnittstellen
Eine Schnittstelle ist eine Typdefinition. Daher wird es als Type Checker/Enforcer in Funktionen, Klassen usw. verwendet.
interface humanInterface{
name:string;
gender:string;
age:number;
}
const kevin: humanInterface={
name:'Kevin Sunders',
gender:'Male',
age: 25,
}
Das humanInterface
oben führt eine strenge Typprüfung für kevin
durch Objekt. Typoskript würde einen Fehler ausgeben, wenn Sie ein weiteres Feld hinzufügen oder den Typ einer der Objekteigenschaften ändern.
Controller
Controller sind dafür verantwortlich, eingehende Anfragen zu empfangen und dem Client zu antworten. Ein Controller arbeitet mit seinem zugehörigen Dienst zusammen.
Dienste
Ein Dienst ist ein Anbieter, der Daten speichert und abruft und mit seinem entsprechenden Controller verwendet wird.
Dekorateure
Ein Decorator ist ein Ausdruck, der eine Funktion zurückgibt und ein target
akzeptiert , name
, und property descriptor
als optionale Argumente. Dekorateure werden als @decorator-name
geschrieben . Sie werden normalerweise an Klassendeklarationen, Methoden und Parameter angehängt.
@Get()
getAll(): Model[] {
return this.testService.getAll();
}
Der @Get
Der obige Dekorator markiert den Codeblock darunter als GET
Anfrage. Dazu später mehr.
Modul
Ein Modul ist ein Teil eines Programms, das eine bestimmte Aufgabe erledigt. Ein Modul in NestJS wird durch Annotieren einer Klasse gekennzeichnet, die mit @Module()
annotiert ist Dekorateur. Nest verwendet die von @Module()
bereitgestellten Metadaten decorator, um die Anwendungsstruktur zu organisieren.
CLI installieren
Um zu beginnen, müssen Sie die NestJS CLI **** mit npm
installieren . Sie können diesen Schritt überspringen, wenn Sie die NestJS-Befehlszeilenschnittstelle bereits auf Ihrem System installiert haben.
npm i -g @nestjs/cli
Dieser obige Codeblock installiert die Nest-CLI global auf Ihrem System.
Erstellen eines neuen Projekts
Um ein neues Projekt zu generieren, führen Sie nest new
aus gefolgt von Ihrem gewünschten Projektnamen. Für diesen Artikel schreiben wir eine einfache Blog-API mit CRUD-Funktionalität, während wir uns an RESTful-Standards halten.
nest new Blog-Api
Dieser Befehl fordert Sie auf, einen Paketmanager auszuwählen, wählen Sie npm
.
Dadurch wird die gesamte Projektstruktur mit einem Test-API-Endpunkt aufgebaut, dessen Port auf 3000
gesetzt ist standardmäßig. Sie können es unter http://localhost:3000
testen nach dem Ausführen von npm run start:dev
Befehl, der den Server im Watch-Modus startet, ähnlich wie nodemon in Express-Apps.
Nach dem Testen des Endpunkts müssen Sie einige der Standarddateien löschen, da Sie sie nicht mehr benötigen. Um dies zu tun;
- Öffnen Sie den src-Ordner und darin
- Löschen Sie
app.controller.spec.ts
, - Löschen Sie
app.controller.ts
, - Löschen Sie
app.service.ts
, - Öffnen Sie
app.module.ts
, - Entfernen Sie den Verweis auf
AppController
in dencontrollers
Array und die Importe, - Entfernen Sie den Verweis auf
AppService
in denproviders
Array und die Importe.
Möglicherweise müssen Sie auch die README.md
ändern um Ihre Spezifikationen zu erfüllen.
Ihre app.module.ts
Datei sollte so aussehen,
//app.module.ts
import { Module } from '@nestjs/common';
@Module({
imports: [],
controllers: [],
providers: [],
})
export class AppModule {}
Umgebungsvariablen
Als bewährte Methode sollten einige vertrauliche Informationen in Ihrem Code nicht veröffentlicht werden. Zum Beispiel Ihr PORT
und Ihren MongoDB URI
.
Lassen Sie uns dies in Ihrem Code beheben.
Auf Ihrem Terminal ausführen
npm i dotenv
Erstellen Sie dann eine .env
Datei in Ihrem Verzeichnis und fügen Sie sie zu Ihrer .gitignore
hinzu Datei. Speichern Sie Ihren PORT
-Variable müssen Sie auch Ihren MongoDB URI
speichern später an gleicher Stelle. Ersetzen Sie nun den exponierten PORT
in Ihrer main.ts
Datei. Importieren Sie dazu die Datei dotenv
Paket und rufen Sie .config()
auf Methode drauf.
import * as dotenv from 'dotenv';
dotenv.config();
Dies sollte Ihre main.ts
sein Datei, nachdem Sie die obigen Schritte ausgeführt haben.
//main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as dotenv from 'dotenv';
dotenv.config();
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(process.env.PORT);
}
bootstrap();
Generieren von Modulen
Um ein NestJS-Modul mit der NestJS-CLI zu generieren, führen Sie das folgende Code-Snippet aus.
nest generate module blogs
Dieser Befehl erstellt ein blogs
Ordner, der eine blogs.module.ts
enthält Datei und registriert BlogsModule
in Ihrer app.module.ts
Datei.
Generieren von Schnittstellen
Lassen Sie uns mithilfe der NestJS-CLI eine Schnittstelle generieren, um die Typprüfung für das Objekt durchzuführen, das Ihre Blog-Posts darstellen wird. Um dies zu erreichen, müssen Sie zuerst cd
in die blogs
Ordner, da empfohlen wird, sie in der Nähe der Domänenobjekte zu speichern, denen sie zugeordnet sind.
cd src/blogs
Führen Sie dann das unten stehende Code-Snippet aus, um die Schnittstelle zu generieren.
nest generate interface blogs
dies erstellt eine blogs.interface.ts
Datei. Hier definieren wir unsere Schnittstelle. wir nennen die Schnittstelle BlogsInterface
.
export interface BlogsInterface {
title: string;
body: string;
category: string;
dateCreated: Date;
}
Bevor Sie weitere Befehle auf Ihrem Terminal ausführen, denken Sie an cd
aus der src
Ordner und durch Ausführen zurück in Ihren Stammordner
cd ../..
Generieren von Diensten und Controllern
Sie müssen eine Dienstklasse generieren, um Daten zu speichern und abzurufen und die gesamte Logik zu verarbeiten, sowie eine Controller-Klasse, um alle eingehenden Anforderungen und ausgehenden Antworten zu verarbeiten.
Dienst
Um einen Dienst zu generieren, führen Sie den folgenden Befehl aus:
nest generate service blogs
Dieser Befehl erstellt zwei Dateien:blogs.service.spec.ts
und die blogs.service.ts
und registriert den Dienst bei den providers
-Array in blogs.module.ts
.
Verantwortlicher
Um einen Controller zu generieren, führen Sie den folgenden Befehl aus:
nest generate controller blogs
Dieser Befehl erstellt zwei Dateien, die blogs.controller.spec.ts
und die blogs.controller.ts
und registriert den Controller im controllers
-Array in blogs.module.ts
.
Damit ist Ihre Blogstruktur fast vollständig, Sie müssen nur noch den BlogsService
erstellen zugänglich für andere Teile Ihres Programms. Sie können dies erreichen, indem Sie einen exports
erstellen -Array in blogs.module.ts
-Datei und Registrieren des BlogsService
in diesem Array.
//blogs.module.ts
import { Module } from '@nestjs/common';
import { BlogsService } from './blogs.service';
import { BlogsController } from './blogs.controller';
@Module({
providers: [BlogsService],
controllers: [BlogsController],
exports: [BlogsService],
})
export class BlogsModule {}
MongoDB(Mongoose).
Installieren Sie Mungo, indem Sie ausführen,
npm install --save @nestjs/mongoose mongoose
Importieren Sie nach der Installation {MongooseModule}
von '@nestjs/mongoose’
in Ihre app.module.ts
Datei. Dann holen Sie sich Ihren MongoDB URI
und speichern Sie es in Ihrer .env
Datei. Wiederholen Sie die Schritte zum Importieren von dotenv
in der app.module.ts
Datei. Dann in den imports
Array rufen Sie .forRoot()
auf -Methode, die Ihren MongoDB URI
übernimmt als Argument für das MongooseModule
. Ähnlich wie mongoose.connect()
in regulären Express-Apps.
@Module({
imports: [BlogsModule, MongooseModule.forRoot(process.env.MONGODB_URI)],
Erstellen eines Schemas.
Lassen Sie uns ein Schema erstellen, um die Form der Blogs in unserer Sammlung zu definieren. Dazu
- Erstellen Sie einen Ordner in Ihren
blogs
nennen Sie ihnschemas
, - Innerhalb der
schemas
Ordner, erstellen Sie eine Datei und nennen Sie sieblogs.schema.ts
.
Dann
Zunächst müssen Sie,
- Importieren Sie die
prop
Dekorateur, dasschema
decorator und dieSchemaFactory
von@nestjs/mongoose
, - Erstellen Sie eine Klasse
Blog
und exportieren, - Verwandeln Sie die Klasse in ein Schema, indem Sie
@Schema()
platzieren Dekorateur über der Klasse, - Erstellen Sie ein konstantes
BlogSchema
, weisen Sie den Rückgabewert des Aufrufs von.createForClass(Blog)
zu mit dem Namen Ihrer Klasse als Argument fürSchemaFactory
die Sie zuvor importiert haben.
//blogs.schema.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
@Schema()
export class Blog {}
export const BlogSchema = SchemaFactory.createForClass(Blog);
Dann müssen Sie die Eigenschaften des Schemas definieren.
Um eine Eigenschaft im Schema zu definieren, müssen Sie jede von ihnen mit @prop()
markieren Dekorateur. Der @prop
decorator akzeptiert ein Optionsobjekt oder eine komplexe Typdeklaration. Die komplexen Typdeklarationen könnten Arrays und verschachtelte Objekttypdeklarationen sein.
//blogs.schema.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
@Schema()
export class Blog {
@Prop({ required: true })
title: string;
@Prop({ required: true })
body: string;
@Prop({ required: true })
category: string;
@Prop({ required: true })
dateCreated: Date;
}
export const BlogSchema = SchemaFactory.createForClass(Blog);
Als nächstes importieren Sie { Document }
von 'mongoose'
.
Erstellen Sie dann einen Union-Typ mit der Schema-Klasse und dem importierten Document
. So,
//blogs.schema.ts
import { Document } from 'mongoose';
export type BlogDocument = Blog & Document;
Ihre endgültige blogs.schema.ts
Datei sollte so aussehen,
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';
export type BlogDocument = Blog & Document;
@Schema()
export class Blog {
@Prop({ required: true })
title: string;
@Prop({ required: true })
body: string;
@Prop({ required: true })
category: string;
@Prop({ required: true })
dateCreated: Date;
}
export const BlogSchema = SchemaFactory.createForClass(Blog);
Schema registrieren
Sie müssen alles in Ihre blogs.module.ts
importieren Datei. Um dies zu erreichen, müssen Sie,
- Importiere
{MongooseModule}
von'@nestjs/mongoose’
, - Importiere
{Blog, BlogSchema}
aus'./schemas/blogs.schema’
- Erstellen Sie einen
imports
Array innerhalb des@module
Dekorateur - Rufen Sie
.forFeature()
auf -Methode auf demMongooseModule
. Dies nimmt ein Array auf, das ein Objekt enthält, das einenname
definiert und einschema
-Eigenschaft, die auf IhrenBlog.name
gesetzt werden sollte und IhrBlogSchema
bzw..
@Module({
imports: [
MongooseModule.forFeature([{ name: Blog.name, schema: BlogSchema }]),
],
Injizierendes Schema
Sie müssen den Blog
einfügen model in blogs.service.ts
mit @InjectModel()
Dekorateur. Um dies zu erreichen, müssen Sie
- importiere
{ Model }
von'mongoose'
, - importiere
{ InjectModel }
von'@nestjs/mongoose’
, - Importiere
{Blog, BlogDocument}
aus'./schemas/blogs.schema’
, - Erstellen Sie einen
constructor
innerhalb desBlogsService
Klasse, - Deklarieren Sie einen
private
-Variable und nennen Sie sieblogModel
und weisen Sie den TypModel<BlogDocument>
zu dazu. Alle Mungo-Methoden werden für diese Variable aufgerufen.
Denken Sie daran, BlogDocument
ist der Vereinigungstyp des Blog
-Klasse und das Mongoose Model
die Sie zuvor erstellt haben. Er wird als generischer Typ für Ihre Variable verwendet.
- Dekoriere
blogModel
mit@InjectModel()
und übergeben SieBlog.name
als Argument.
constructor(
@InjectModel(Blog.name)
private blogModel: Model<BlogDocument>,
) {}
Funktionsweise des Routings
Inzwischen müssen Sie bemerkt haben, dass der @Controller
decorator hat die Zeichenkette 'blogs'
hineingegangen. Das bedeutet, dass der Controller alle Antworten sendet und alle Anfragen verarbeitet, die auf http://localhost/3000/blogs
gestellt werden .
Als Nächstes implementieren Sie die Dienst- und Controller-Logik.
Dienst- und Controller-Logik.
Es ist endlich an der Zeit, Ihre CRUD-Funktionalität zu implementieren.
Bevor wir beginnen, müssen Sie Ihren Controller einrichten. Beginnen Sie damit, etwas HTTP
zu importieren Methoden-Decorators in Ihren Controller.
//blogs.controller.ts
import {
Controller,
Body,
Delete,
Get,
Post,
Put,
Param,
} from '@nestjs/common';
Anschließend müssen Sie den Dienst importieren und registrieren, damit Sie darauf zugreifen und die Schnittstelle zur Typprüfung importieren können.
//blogs.controller.ts
import { BlogsInterface } from './blogs.interface';
import { BlogsService } from './blogs.service';
Um Ihren Dienst zu registrieren, erstellen Sie einen constructor
innerhalb des BlogsController
Klasse und deklarieren Sie eine private readonly
Variable service
und setzen Sie seinen Typ auf BlogsService
.
constructor(private readonly service: BlogsService) {}
Jetzt, da Sie alles eingerichtet haben, können wir loslegen.
Erstellen
Dienstlogik
Importieren Sie { BlogsInterface }
aus './blogs.interface'
und füge ein async
hinzu Funktion an den BlogsService
Klasse namens createBlog
, die einen Parameter blog
annehmen wird , mit seinem Typ als BlogInterface
, und sein Rückgabetyp als Promise
mit einem generischen <Blog>
Typ.
async createBlog(blog: BlogsInterface): Promise<Blog> {
return await new this.blogModel({
...blog,
dateCreated: new Date(),
}).save();
}
Controller-Logik
In Ihrem BlogsController
Klasse einen async
hinzufügen Funktion für die Klasse. Nennen Sie es createBlog
und markieren Sie es mit dem @Post
decorator, der es als POST
definiert Anfrage.createBlog
nimmt einen Parameter blog
, mit seinem Typ als BlogInterface
. Markieren Sie den Parameter mit @Body
decorator, der den gesamten body
extrahiert Objekt aus req
-Objekt und füllt den dekorierten Parameter mit dem Wert von body
.
@Post()
async createBlog(
@Body()
blog: BlogsInterface,
) {
return await this.service.createBlog(blog);
}
Lesen
Fügen Sie zwei async
hinzu Methoden, eine zum Zurückgeben eines einzelnen Blogposts und die zweite zum Zurückgeben aller Blogposts.
Dienstlogik
async getAllBlogs(): Promise<Blog[]> {
return await this.blogModel.find().exec();
}
async getBlog(id: string): Promise<Blog> {
return await this.blogModel.findById(id);
}
Controller-Logik
@Get()
async getAllBlogs() {
return await this.service.getAllBlogs();
}
@Get(':id')
async getBlog(@Param('id') id: string) {
return await this.service.getBlog(id);
}
Die async
Funktionen sind mit dem @Get
gekennzeichnet decorator, der es als GET
definiert Anfrage.
Die zweite async
Der Decorator der Funktion hat ein Argument ':id'
. Das übergeben Sie an @Param
Dekorateur. Der Parameter ist mit dem @Param('id')
gekennzeichnet die die params
extrahiert -Eigenschaft aus req
-Objekt und füllt den dekorierten Parameter mit dem Wert von params
.
Aktualisieren
Lassen Sie uns die Logik für PUT
implementieren Anfrage.
Dienstlogik
async updateBlog(id: string, body: BlogsInterface): Promise<Blog> {
return await this.blogModel.findByIdAndUpdate(id, body);
}
Controller-Logik
@Put(':id')
async updateBlog(
@Param('id')
id: string,
@Body()
blog: BlogsInterface,
) {
return await this.service.updateBlog(id, blog);
}
Die async
Der zweite Parameter der Funktion ist mit @Body()
gekennzeichnet decorator, der den gesamten body
extrahiert Objekt aus req
-Objekt und füllt den dekorierten Parameter mit dem Wert von body
.
Löschen
Lassen Sie uns die Logik für delete
implementieren Anfragen.
Dienstlogik
async deleteBlog(id: string): Promise<void> {
return await this.blogModel.findByIdAndDelete(id);
}
Das Promise
Der generische Typ ist void
weil ein Delete
Anfrage gibt ein leeres Promise zurück.
Controller-Logik
@Delete(':id')
async deleteBlog(@Param('id') id: string) {
return await this.service.deleteBlog(id);
}
API testen
Um diese API zu testen, sollten Sie ein API-Testtool verwenden. Für diesen Artikel verwende ich ein beliebtes API-Testtool namens Postman. Ich werde zum Testen zufällige Daten zu beliebten Themen verwenden.
Erstellen
Erstellen Sie einen POST
Anfrage an http://localhost/3000/blogs
Mit den folgenden JSON-Objekten werden alle Daten zu Ihrer Datenbank hinzugefügt.
{
"title": "jeen-yuhs",
"body": "The life of superstar rapper Kanye West is currently streaming on Netflix - and according to our jeen-yuhs review, it's a fascinating watch. -credit:Radio Times",
"category":"Music"
}
{
"title": "Why You Should Always Wash Your Hands",
"body": "Germs from unwashed hands can be transferred to other objects, like handrails, tabletops, or toys, and then transferred to another person's hands.-credit cdc.gov",
"category":"Health"
}
{
"title": "Why You Should Follow me on Twitter",
"body": "Well, Because I asked nicely",
"category":"Random"
}
Sie sollten einen 201
erhalten Antwort und das erstellte Blog mit einem Datum und einer _id
hinzugefügt.
Lesen
Machen Sie ein GET
Anfrage an http://localhost/3000/blogs
. Dies sollte ein
200
Antwort mit einem Array aller Daten, die Sie zuvor hinzugefügt haben. Kopieren Sie die _id
-Eigenschaft eines der Array-Objekte.
Machen Sie ein weiteres GET
Anfrage an http://localhost/3000/blogs/id
mit der zuvor kopierten ID. Dies sollte einen 200
zurückgeben Antwort mit den Daten des Objekts, dessen ID verwendet wurde, um die Anfrage zu stellen.
Aktualisieren
Machen Sie einen PUT
Anfrage an http://localhost/3000/blogs/id
mit den unten stehenden Daten. Die id
sollte durch die zuvor kopierte ersetzt werden. Dies sollte einen 200
zurückgeben Antwort und aktualisiert das Objekt mit der id
hinter den Kulissen. wenn Sie ein weiteres GET
ausführen Anforderung sollten Sie das aktualisierte Objekt erhalten.
{
"title": "why you Should Cut your Nails",
"body": "It's important to trim your nails regularly. Nail trimming together with manicures makes your nails look well-groomed, neat, and tidy.- credit:WebMD",
"category":"Health"
}
Löschen
Machen Sie ein DELETE
Anfrage an http://localhost/3000/blogs/id
.Dies sollte einen 200
zurückgeben Antwort und löscht das Objekt mit der id
hinter den Kulissen. wenn Sie ein weiteres GET
ausführen Bitte sehen Sie das gelöschte Objekt nicht.
Fazit
Damit sind wir endlich am Ende dieses Artikels angelangt. Lassen Sie uns zusammenfassen, was Sie behandelt haben.
- Was NestJS ist
- Terminologien in NestJS,
- Erstellen einer NestJS-App
- Integration von MongoDB in eine NestJS-App
- Manipulation und NestJS-App,
Das ist ziemlich viel, herzlichen Glückwunsch, dass Sie es so weit geschafft haben.
Den Code finden Sie auf github.
Viel Glück auf Ihrer NestJS-Reise!