Express: il framework per lo sviluppo di app web con Node JS

Corso completo Web Developer - Parte 3 - 3.1

Introduzione

In questo articolo, esploreremo Express, un framework molto utilizzato per lo sviluppo di applicazioni web basate su Node.js. Inizieremo con una breve introduzione a che cosa sono i framework e alle loro funzionalità. Successivamente, ci addentreremo nella creazione della nostra prima applicazione web con Rxpress, mettendo in evidenza le parti importanti del framework.

Introduzione ai framework e a Express

Express è un pacchetto NPM, la stessa cosa che abbiamo visto con one-liner-joke nell'articolo precedente ma con la differenza che può fare tanto...ma veramente tanto per noi! 🙂

Che cosa è Express?

Quando navighiamo in internet, ci sono due parti coinvolte: il Client (noi) e il Server (dove sono le informazioni). Il nostro computer chiede qualcosa al server, e il server deve capire cosa vogliamo e darci la risposta giusta. Express è uno strumento che è responsabile nel lato Server e serve a far funzionare tutto il processo affinchè noi (il Client) possiamo ottenere la risposta che vogliamo.

Che cosa è un Framework?

Generalmente con il termine Framework o Libreria si riferisce semplicemente a codice scritto da altre persone che stai utilizzando nel tuo progetto.

La differenza risiede nello scopo ultimo di questi codici. Una libreria solitamente la puoi aggiungere in qualsiasi momento nel tuo progetto e serve per risolvere un determinato e singolo problema.

Un framework è del codice che può determinare il modo in disegniamo la struttura di un'applicazione e quindi può avere un effetto più dirompente nel progetto ed è una cosa che spesso viene implementata alla nascita di un progetto.

In parole semplici parliamo di codice che utilizziamo nel nostro progetto e che è stato scritto da altri programmatori.

In ogni caso non preoccuparti, ci schiariremo le idee man mano che andremo avanti in questa lezione e le prossime che si baseranno tutte su Express.

Creazione della nostra prima applicazione Express passo-passo

Prepariamo la base del nostro progetto Express. Dobbiamo:

  1. Creare una cartella per il nostro progetto
  2. Inizializzare il progetto con NPM
  3. Installare Express
  4. Creare il file index.js e scrivere il codice per avviare il server
mkdir express_one
cd express_one
npm init -y
npm install express
touch index.js (in Windows PowerShell usa il comando "New-Item" al posto di "touch")

Come puoi vedere, abbiamo creato una cartella chiamata express_one e ci siamo spostati all'interno di essa. Successivamente abbiamo inizializzato il progetto con NPM e installato Express. Infine abbiamo creato il file index.js che sarà il nostro punto di partenza per il nostro server.

Io ho aperto il progetto con il comando code . che richiede una configurazione iniziale per funzionare. Se non hai ancora configurato VS Code per aprire i progetti con il comando code . puoi sempliecmente aprire il programma VS Code e poi aprire la cartella del progetto da lí.

Ora che abbiamo aperto il progetto con VS Code inseriamo il "boilerplate" per avviare un server con Express.

const express = require('express')

Qui stiamo importando il modulo Express e lo stiamo salvando nella variabile express.

const app = express()

Di seguito aggiungiamo una variable app e gli assegniamo una nuova istanza di Express.

const port = 3000

A questo punto creiamo una nuova variabile port e assegnamo il valore 3000 che è una delle tante porte standard per un server.

app.listen(port, () => {
  console.log(`Server in esecuzione sulla porta ${port}`)
});

E qui stiamo dicendo a Express di mettersi in ascolto sulla porta 3000 e di creare un log in console "Server in esecuzione sulla porta 3000" quando il server è pronto.

Il risultato finale dovrebbe essere questo:

const express = require('express')
const app = express()
const port = 3000

app.listen(port, () => {
  console.log(`Server in esecuzione sulla porta ${port}`)
});

Possiamo quindi avviare il server con il comando node index.js e notare il log in console "Server in esecuzione sulla porta 3000".

Nota come il cursore nel terminale sia bloccato sulla riga Server in esecuzione sulla porta 3000. Questo significa che il server è in esecuzione ed in attesa di richieste HTTP da processare e non possiamo più eseguire altri comandi nella console. Per interrompere il server dobbiamo premere CTRL + C e il server si interromperà.

Che cosa significa che è in attesa di richieste HTTP? Significa che siamo pronti a fare una richiesta al nostro server Express esattamente allo stesso modo come quando navighiamo e andiamo su un sito web.

Proviamo ad aprire il browser e andare su http://localhost:3000 e vediamo cosa succede.

Noteremo questa schermata bianca ed un errore che ci dice che non vi è nessuna pagina all'indirizzo "/". Questo è normale, non abbiamo ancora creato nessuna pagina e quindi il browser non può mostrare nulla. Non ti preoccupare perchè risolveremo in un attimo.

Ora prova a visitare l'indirizzo http://localhost:5000 e vedrai che l'errore cambia.

Questo ci fa capire che il server è in ascolto sulla porta 3000 ma semplicemente non ha ancora nessun percorso configurato per rispondere alla richiesta HTTP "/".

Noterai che utilizzerò il termine endpoint e con questo intendo un percorso che può essere raggiunto da un browser per entrare in contatto con il server che stiamo provando a raggiungere, in questo caso il nostro server Express.

Quindi passiamo adesso alla crezione del nostro primo endpoint in un server Express 😃

Creare un endpoint in un server Express

La parte del nostro server "app.listen" deve trovarsi sempre alla fine del file index.js quindi andiamo ad aggiungere il seguente blocco di codice prima di "app.listen".

app.get('/', (req, res) => {
  res.send('Hello World!')
})

Questo è il nostro primo endpoint e stiamo dicendo a Express di rispondere alla richiesta HTTP GET alla root del nostro server. In questo caso la root è http://localhost:3000 e stiamo dicendo a Express di rispondere con la stringa "Hello World!".

Quando aggiungiamo una root dobbiamo riavviare il server Express. Per farlo possiamo semplicemente premere CTRL + C per interrompere il server e poi eseguire nuovamente il comando node index.js per riavviare il server.

Quando il server è pronto vedremo il log in console "Server in esecuzione sulla porta 3000" quindi andiamo sul browser all'indirizzo http://localhost:3000 e vediamo che cos'è cambiato.

Come puoi notare ora facendo una richiesta GET alla root del server otterremo una risposta con il testo "Hello World!" 🥳

Gli argomenti req e res che vedi sono oggetti che corrispondono a Request e Response che Express ci mette a disposizione per tradurre le richieste HTTP in entrata e gestire le risposte HTTP in semplici oggetti JavaScript.

Il metodo send che stiamo utilizzando è un metodo che ci permette di inviare una risposta HTTP al client che ha fatto la richiesta. In questo caso stiamo inviando una risposta HTTP con il testo "Hello World!".

Abbiamo quindi creato con successo il nostro primo endpoint in un server Express.

Imparare a gestire il routing system con Express

Quando arriva una richiesta HTTP al server Express, questa sarà semplicemente del testo che contiene tutte le informazioni relative a quella richiesta. Express ci mette a disposizione questi oggetti Request e Response con i quali possiamo facilmente accedere a tutte le informazioni relative alla richiesta HTTP lavorando appunto con oggetti JavaScript ben strutturati anzichè con lunghe e complesse stringhe di testo.

Quando inviamo una risposta al Client possiamo decidere di inviare diversi tipi di risposte. Spesso il formato utilizzato è JSON e infatti voglio proprio farti vedere come inviare una risposta in formato JSON.

Andiamo ad aggiungere un nuovo endpoint al nostro server Express che risponderà alla richiesta HTTP GET all'indirizzo http://localhost:3000/margherita.

app.get('/margherita', (req, res) => {
  res.json({
    pomodoro: true,
    mozzarella: true,
    basilico: true,
    salame: false,
    prezzo: 3.50
  })
})

Questa volta anzichè utlizzare il Browser proviamo ad utilizzare Postman. Se ti sei perso la lezione dove spiego come installare Postman puoi recuperarla qui: Installare Postman.

Non dimenticarti che devi riavviare il server Express prima di poter testare il nuovo endpoint.

Questo è il risultato che dovresti ottenere quando provi a fare una richiesta HTTP GET all'indirizzo http://localhost:3000/margherita con Postman.

Come puoi notare otteniamo una risposta in formato JSON :)

Adesso proviamo ad inviare la stessa richiesta ma questa volta inviandola con il metodo HTTP POST e vediamo cosa succede.

Come puoi notare otteniamo un errore 404. Questo perchè quando abbiamo aggiunto il nostro endpoint /margherita abbiamo specificato che questo endpoint dev'essere di tipo GET quando abbiamo scritto nel nostro file app.get('/margherita').... Se avessimo scritto app.post('/margherita')... avremmo invece definito l'endpoint come POST e non come GET.

Utilizzo dei path parameters

Un path parameter è un parametro che viene passato all'interno dell'URL.

Per esempio, possiamo avere un endpoint /pizze che restituisce al client i nomi di tutte le pizze disponibili nel nostro menù. Potremmo anche avere un endpoint /pizze/margherita che restituirebbe al client soltanto la pizza margherita e in aggiunta i dettagli di questa pizza. In questo caso il termine margherita che segue pizza e un path parameter ovvero un parametro che stiamo specificando all'interno del percorso.

Proviamo ad aggiungere un endpoint chiamato /pizze che restituisce una lista di tre pizze.

app.get('/pizze', (req, res) => {
  res.json([
    {
      nome: 'Margherita',
      prezzo: 3.50
    },
    {
      nome: 'Marinara',
      prezzo: 3.50
    },
    {
      nome: 'Quattro Stagioni',
      prezzo: 3.50
    }
  ])
})

Ora proviamo a chiamre uno di questi tre endpoint con Postman.

Vediamo appunto che otteniamo una lista di tre pizze. A questo punto aggiungiamo un nuovo endpoint chiamato /pizze/margherita che restituisce come risposta la pizza margherita ed i dettagli di questa pizza

app.get('/pizze/margherita', (req, res) => {
  res.json({
    nome: 'Margherita',
    prezzo: 3.50
  })
})

Possiamo notare che siamo riusciti a rispondere al client con la sola pizza margherita. Potremmo fare la stessa cosa con le altre due pizze perchè in questo caso abbiamo soltanto tre pizze. Pensa però se avessimo 100 tipologie di pizze diverse. In questo caso diventerebbe molto poco pratico, poco efficiente e creeremmo un caos nel file index.js.

Per ovviare a questo problema vengono utilizzati i parametri dinamici.

Anzichè definire un endpoint /pizze/margherita possiamo definire un endpoint /pizze/:nome dove :nome è un parametro dinamico che possiamo utilizzare per filtrare la pizza che vogliamo dalla lunga lista di pizze a disposizione.

Andiamo a modificare il nostro endpoint /pizze/margherita in /pizze/:nome e il suo codice all'interno per ottenere questo risultato:

app.get('/pizze/:nome', (req, res) => {
  res.json({
    nome: req.params.nome,
    prezzo: 3.50
  })
})

Ora proviamo a chiamre l'endpoint utilizzando un'altra tipologia di pizza, ad esempio la marinara e vediamo che cosa succede.

Vedremo che il server risponderà con la pizza marinara e se provassimo a chiamare l'endpoint utilizzando qualsiasi altro nome questo ci ritornerà la risposta con il nome della pizza che abbiamo specificato. In questo modo non dobbiamo più specificare un endpoint per ogni singola pizza ma possiamo utilizzare un solo endpoint per tutte le pizze. Molto più comodo, no? :)

Gestione delle Query Strings in Express

Ora che abbiamo parlato di path parameters che proseguono il nome dell'endpoint dopo il carattere : possiamo passare a parlare delle query strings.

Le query strings sono sempre parametri che vengono passati all'interno dell'URL ma queste sono scritte dopo il carattere del punto interrogativo ? e sono utilizzate per passare informazioni aggiuntive al server.

Andiamo a modificare la risposta nell'endpoint /pizze/:nome per ottenere questo risultato:

app.get('/pizze/:nome', (req, res) => {
  res.json({
    nome: req.params.nome,
    prezzo: 3.50,
    dimensione: req.query.dimensione
  })
})

Vedi che abbiamo aggiunto un nuovo parametro nella risposta dimensione dove abbiamo utilizzato req.query.dimensione per ottenere il valore della query string dimensione.

Ora da Postman proviamo a chiamare l'endpoint /pizze/marinara?dimensione=grande e vediamo cosa succede.

Come puoi notare abbiamo ottenuto il valore grande che abbiamo passato dopo il punto interrogativo ? nell'URL accedendo all'oggeto query all'interno di req.

Probabilmente ti starai chiedendo che differenza c'è tra i path parameters e le query strings visto che entrambi sono una soluzione per passare in modo dinamico informazioni aggiuntive al server.

Le query strings possono più facilmente essere opzionali rispetto ai path parameters quindi se non passassimo il parametro dimensione otterremo semplicemente un valore di undefined mentre se non passassimo il parametro nome otterremmo un errore come path parameter otterremo un errore poichè il nostro endpoint è stato definito come /pizze/:nome il che significa che si aspetta un parametro obbligatorio dopo il nome pizze.

Inoltre le query strings rispetto ai path parameters non più facili da gestire in quanto non definiscono la struttura del nostro URL rispetto ai path parameters quindi possiamo più facilmente decidere di aggiungere o rimuovere query strings senza dover modificare la struttura dell'URL e potenzialmente impattare persone che utilizzano attivamente quel determinato endpoint.

Ci sono altri motivi per cui le query strings sono più utilizzate rispetto ai path parameters ma non voglio dilungarmi troppo su questo argomento perchè non è il punto principale di questa lezione.

Utilizzo di Nodemon per il riavvio automatico del server

Hai notato quante volte abbiamo dovuto riavviare il nostro server ogni volta che abbiamo modificato un endpoint? Non sarebbe molto più comodo se il server si riavviasse automaticamente ogni volta che salviamo un file?

C'è una soluzione a tutto ciò e si chiama nodemon che è un pacchetto npm che ci permette di riavviare automaticamente il server ogni volta che salviamo un file.

Ti consiglio di installare questo pacchetto in modo globale sul tuo computer di modo che potrai utilizzarlo automaticamente su qualsiasi progetto creerai in futuro.

Per installarlo è semplicissimo e ti basta eseguire questo comando nella console:

npm install -g nodemon

Per utilizzarlo in un progetto come ad esempio quello che abbiamo appena fatto ti basterà eseguire il comando nodemon index.js anzichè node index.js.

Conclusione

Complimenti a te gorgaTecher! Sei arrivato alla fine di questa lezione in cui hai iniziato a sviluppare un applicazione web con Express!

Spero che questa lezione ti sia piaciuta e che sei pronta/o alla prossima in cui andremo ad imparare come ritornare delle pagine HTML dal nostro server anzichè risposte JSON il che significa che potremo creare e visualizzare delle vere e proprie pagine web che vengono servite direttamente dal nostro server!

Ricordati di divertirti durante il nostro viaggio nella programmazione e di mantenere alta la motivazione.

Ti aspetto alla prossima lezione, ora ti saluto 👋

Buona programmazione! 🚀