Come creare la tua prima applicazione NestJS

Iacopo Ciao
7 min readSep 21, 2020

--

In questo articolo, ti guiderò attraverso lo sviluppo di una semplice applicazione rest per TODO, fornendoti una panoramica sul framework NestJS.

Photo by Sereja Ris on Unsplash

Che cos’è NestJS?

NestJS è un framework per lo sviluppo rapido di applicazioni backend la cui struttura, fortemente ispirata a quella di Angular, lo rende perfetto per la realizzazione di progetti con stack MEAN.

Quando utilizzare NestJS?

Nest è particolarmente indicato per lo sviluppo di applicazioni che gestiscono un’enorme quantità di richieste con una piccolissima quantità di dati elaborati lato server e tempi di risposta istantanei (e-commerce, live chat, ecc ..).

Perché usare NestJS?

I vantaggi nell’utilizzo di NestJS sono innumerevoli. I più importanti (imho) che voglio evidenziare sono:

  • Type checking: con il Typescript sfruttiamo tutta la potenza del javascript senza incorrere nei problemi di tipizzazione.
  • Modulare: tramite la suddivisione in moduli possiamo isolare i nostri componenti in base al domain boundary.
  • Dependency Injection: grazie al container DI siamo in grado di scrivere codice disaccoppiato e testabile.
  • Adapters: Nest integra al suo interno tutte le librerie javascript/typescript più utilizzate e testate dalla community e fornisce agli sviluppatori tutti gli strumenti necessari per poter contribuire alla raccolta.
  • Angular Like: la struttura familiare ci permette di passare facilmente da frontend a backend senza dover cambiare l’approccio di sviluppo ad ogni iterazione.
  • CLI: possiamo sviluppare le nostre funzionalità senza doverci preoccupare del boilerplate iniziale

Cominciamo a scrivere codice

  • recuperare la lista di tutti i todo
  • recuperare un todo singolo
  • inserire un todo
  • modificare un todo
  • eliminare un todo

Di conseguenza delle seguenti API:

  • [GET] todos
  • [GET] todos/{id}
  • [POST] todos
  • [PUT] todos/{id}
  • [DELETE] todos/{id}
Ehm 😅

step 0: Setup

Configuriamo il nostro progetto con due semplici comandi da terminale:

npm i -g @nestjs/cli
nest new TodoBackend

Per essere sicuri che tutto sia okay, eseguiamo $ npm run start nella cartella todo-backend:

NestJS bootstrap logs

step 1: Module

I moduli sono il meccanismo che ci permette di separare i nostri componenti in base a un dominio di appartenenza e, nell’atto pratico, di istruire il container DI sulle loro interazioni nella fase di bootstrap.

Il modulo principale con cui viene eseguito il bootstrap viene definito modulo radice e, nelle applicazioni generate tramite CLI, lo troviamo nella cartella src sotto il nome di AppModule.

La nostra applicazione, essendo molto piccola e con un’unica funzionalità, potrebbe sfruttare direttamente il modulo radice per gestire le proprie dipendenze. Ci sono almeno due buone ragioni per cui non lo faremo in questa guida:

  • Non è un caso tipico e di conseguenza difficilmente applicabile in un contesto reale.
  • Non saremmo disaccoppiati, perdendo quindi in manutenibilità e in portabilità del nostro codice.

Creiamo il nostro modulo tramite la CLI:

nest generate module todo

Appena generato, la CLI si occuperà anche di aggiornare AppModule importando TodoModule come modulo feature 🎉

step 2: Entity

Una entity è una classe che mappa una tabella (o collezione) del nostro database (definizione molto pragmatica).

Creiamo la nostra entity tramite la CLI:

nest generate class todo/entities/Todo --no-spec

step 3: Repository

Adesso che abbiamo la nostra entity non ci resta che persisterla attraverso un ORM!

Per questa guida ho deciso di utilizzare Typeorm e di limitarci a configurare una connessione a un database sqlite.

Per prima cosa installiamo le dipendenze:

npm i @nestjs/typeorm typeorm sqlite3

Modifichiamo AppModule andando ad importare TypeOrmModule con il metodo statico forRoot, inserendo le configurazioni che ci servono:

Aggiungiamo TypeOrmModule anche sul nostro , questa volta utilizzando il metodo forFeature, specificando Todo come entity da gestire:

Ora che abbiamo configurato Typeorm possiamo finalmente aggiornare il nostro Todo con tutte le annotazioni necessarie:

Typeorm e le sue annotazioni potete approfondirli consultando il link allegato a inizio step. Per i metodi forRoot e forFeature di TypeOrmModule, potete consultare la sezione database nella documentazione ufficiale di NestJS: https://docs.nestjs.com/techniques/database

step 4: DTO

Per evitare di esporre le nostre entities al di fuori del nostro business logic layer, definiamo un set di oggetti che verranno utilizzati per gestire la comunicazione in entrata e in uscita dai nostri servizi: i DTO (Data Transfer Object).

step 5: Service

Il service è il “pacchetto” dove andremo a incapsulare la nostra logica di business, esponendo un set di funzionalità pronte all’utilizzo.

Definiamo gli oggetti che popoleranno il nostro service layer:

nest generate service todo/services/todo

Nel service appena creato, implementiamo i metodi findAll, findOne, add, edit e delete che, attraverso i DTO, verranno consumati dal nostro controller.

Per disaccoppiare la logica di conversione da Entity a DTO e viceversa dalla business logic, creiamo un TodoMapperService:

nest generate service todo/services/TodoMapper

Adesso implementiamo il nostro TodoService: iniettiamo, tramite Dependency Injection, il Todo Repository fornito da Typeorm e il nostro TodoMapperService:

step 6: Controller

Eccoci arrivati all’ultimo layer della nostra scalata allo stack di NestJS! Per creare il nostro controller utilizzeremo per l’ultima volta la nostra utilissima CLI con questo comando:

nest generate controller todo/controllers/todo

Implementiamo i metodi che rispecchieranno le chiamate rest che abbiamo elencato all’inizio dell’articolo, decoriamoli con le routing annotations e agganciamoli ai metodi di TodoService:

ATTENZIONE: la serializzazione dei DTO non è attiva a meno che non decoriate il metodo del vostro controller con ClassSerializerInterceptor

@Post()
@UseInterceptors(ClassSerializerInterceptor)
public add(@Body() todo: AddTodoDto): Promise<TodoDto> {

Nel prossimo step approfondiremo questo argomento andando a sviluppare una soluzione che ci permetta di centralizzare questo interceptor 😉

step 7: Validation

I nostri DTO sono pronti per viaggiare spediti come macchine di formula 1 all’interno del protocollo http ma manca un ultimo pezzo: la validazione dei suoi dati.

per gestire la validazione dei nostri campi, NestJS fornisce una pipe per la validazione che sfrutta le librerie class-transformer e class-validator. Per poterla utilizzare però, dobbiamo installare le sue dipendenze nel progetto:

npm i class-transformer class-validator

Aggiungiamo nelle pipes globali il validatore ValidationPipe:

E adesso decoriamo i nostri DTO:

ATTENZIONE: Una volta compilata la nostra applicazione, tutti i DTO che abbiamo definito fino ad adesso verranno convertiti in oggetti javascript, questo significa che non verrà effettuato nessun type check sui valori che verranno assegnati ai suoi campi!

Quindi inostri validatori funzioneranno solo fino a quando gli verranno passati i valori del tipo giusto? NO.

La libreria class-validator possiede al suo interno anche un set di validatori atti appositamente a eseguire il type check dei nostri campi a runtime:

step 8: Run!

È arrivato finalmente il momento di eseguire la nostra applicazione! 🎉

Per eseguirla normalmente basterà lanciare il comando

npm run start

Se invece abbiamo bisogno di entrare in debug nel nostro codice, dovremo eseguire il comando

npm run start:debug

step 9: Enable CORS

Dopo aver sviluppato il nostro backend, molto probabilmente vorremo sviluppare una applicazione frontend e provare a contattarlo, qui entra in gioco il CORS:

Il Cross-Origin Resource Sharing (CORS) è un meccanismo che usa header HTTP addizionali per indicare a un browser che un’applicazione Web in esecuzione su un’origine (dominio) dispone dell’autorizzazione per accedere alle risorse selezionate da un server di origine diversa. […] Per ragioni di sicurezza, i browser limitano le cross-origin HTTP requests che vengono generate all’interno degli scripts.

https://developer.mozilla.org/it/docs/Web/HTTP/CORS

Per abilitare CORS basta intervenire nuovamente nel main.ts invocando il metodo enableCors() con tutti i parametri di configurazione di cui necessitiamo. Per semplicità, noi abiliteremo tutto! (Freedom! 🤟)

step 10: Test

I test sono assolutamente necessari quando si desidera realizzare un’applicazione manutenibile: ci prevengono dai più comuni errori di sviluppo e dalle possibili regressioni dovute alla modifica di una funzionalità esistente.

Quando generiamo un nuovo componente tramite CLI, viene generato automaticamente anche il suo file di test. Proviamo a farne uno:

Per lo sviluppo dei test, Nest utilizza sotto al cofano Jest

per ulteriori informazioni visionate la documentazione NestJS https://docs.nestjs.com/fundamentals/testing

Potete trovare i sorgenti di questo articolo sul mio repository Github, sentitevi liberi di mettere una ⭐️ 😁

Conclusioni

Realizzando l’applicazione descritta in questo articolo ho potuto constatare in prima persona quanto sia veloce e potente questo framework: ti permette di essere estremamente rapido e flessibile senza dover rinunciare assolutamente a nulla. NestJS passa a pieni voti gli esami e può occupare meritatamente il suo posto nella top list dei framework per lo sviluppo web.

Se hai apprezzato questa guida, non dimenticarti di 👏 e di condividerla con tutte le persone che potrebbero trarne beneficio 😃

So long, and thanks for all the fish 🐬

--

--

No responses yet