In questo articolo, ti guiderò attraverso lo sviluppo di una semplice applicazione rest per TODO, fornendoti una panoramica sul framework NestJS.
Che cos’è NestJS e quando utilizzarlo?
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.
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
“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.”
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}.
step 0: Setup
Configuriamo il nostro progetto con due semplici comandi da terminale:
Per essere sicuri che tutto sia okay, eseguiamo $ npm run start nella cartella todo-backend:
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:
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:
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:
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
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:
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:
ATTENZIONE: la serializzazione dei DTO non è attiva a meno che non decoriate il metodo del vostro controller con ClassSerializerInterceptor
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:
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
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 🐬