Come creare pagine web dinamiche con EJS in Node.js

Corso completo Web Developer - Parte 3 - 3.1

Introduzione

Nella lezione precedente abbiamo visto per la prima volta il framework Express, come definire endpoints e come servire delle risposte HTTP al Client.

In questa lezione scoprirai come vengono create pagine web dinamicamente utilizzando EJS! EJS viene definito un template engine ovvero un sistema per generare pagine web dinamicamente combinando codice HTML a codice JavaScript.

Cos'è il templating

Definizione del termine

A volte i termini in Inglese specialmente se non si ha un'ottima conoscenza della lingua possono far sembrare dei concetti semplici più difficili di quelli che in realtà sono.

Voglio farti subito un esempio pratico per farti capire cos'è ed a cosa serve il concetto di templating facendoti.

Hai visto come nel sito gorgaTech in cui stai leggendo questo articolo tutte le pagine si somigliano, hanno lo stesso layout, la stessa struttura, il menù di navigazione in alto è lo stesso, la barra laterale è la stessa, il footer in fondo alla pagina è lo stesso e cosí via e l'unica cosa che effettivamente cambia è il contenuto testo e immagini?

Attraverso il concetto di templating si cerca di definire un pattern che si ripete in più pagine e che noi poi possiamo facilmente modificarne il contenuto dinamicamente.

Ad esempio questo sito non ha un file con tutto l'HTML, il CSS e JavaScript per ogni articolo ma soltanto un singolo file che poi viene utilizzato per generare tutte le altre pagine.

Questo singolo file a sua volta si basa su più singoli file che poi vengono combinati per generare la pagina finale. Ad esempio un file che contiene il layout generale del sito, un file che contiene il menù di navigazione, un file che contiene il footer, un file che contiene la barra laterale e cosí via.

Vantaggi nell'utilizzo

Il concetto di templating ha molti vantaggi, tra questi:

Riduzione del codice duplicato: se hai un sito con molte pagine e tutte utilizzano lo stesso layout, puoi definire un singolo file che contiene il codice che forma il e poi utilizzarlo per generare tutte le altre pagine. In questo modo non devi scrivere più volte lo stesso codice e se vuoi modificare qualcosa, lo fai una volta sola e non in ogni singola pagina.

Miglioramento del mantenimento del sito: se hai un sito con molte pagine e vuoi modificare una cosa che si ripete su tutte le pagine puoi immaginare quanto meglio sia avere la possibilità di modificare una sola volta il codice e non in ogni singola pagina.

Velocità di sviluppo: non dovendo riscrivere il codice per ogni singola pagina puoi concentrarti maggiormente sul contenuto e sulle funzionalità che vuoi aggiungere al sito anzichè dover ripetere lo stesso codice per costruire lo stesso menù decine o centinaia di volte.

Adesso basta con la teoria e passiamo alla pratica 😃

Creazione di un progetto Express

La primissima cosa da fare sarà quella di creare un nuovo progetto Express.

Per farlo apriamo il terminale, ci spostiamo nella cartella dove vogliamo creare il progetto, creiamo una cartella per il progetto e ci spostiamo all'interno di essa.

mkdir tutorial_ejs_templating
cd tutorial_ejs_templating

Ora inizializziamo il progetto con NPM, dopodichè installiamo Express e creiamo un file index.js

npm init -y
npm install express
touch index.js (in Windows PowerShell usa il comando "New-Item" al posto di "touch")
ls

Come puoi notare ho anche eseguito il comando ls per controllare cosa ci fosse all'interno della cartella dopo aver eseguito tutti i comandi e quindi accertarmi che tutto sia stato creato correttamente.

A questo punto apriamo l'intero progetto su VS Code e aggiungiamo il boilerplate per un server Express.

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

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

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

Ora che abbiamo il server Express possiamo avviarlo con il comando nodemon index.js nella root del progetto e verificare che funzioni correttamente andando sul browser all'indirizzo http://localhost:3000 verificando che appunto la richiesta ci ritorna la stringa Hello World!.

nodemon index.js

Aggiungere EJS come template engine

Siamo pronti a configurare EJS come template engine per il nostro progetto Express.

Per farlo installiamo il pacchetto ejs con NPM e lo aggiungiamo al file index.js come middleware di Express.

npm install ejs
const express = require('express');
const app = express();
const port = 3000;
const path = require('path'); // aggiungi questa linea

app.set('view engine', 'ejs'); 
app.set('views', path.join(__dirname, '/views'));

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

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

Come puoi notare abbiamo aggiunto tre righe di codice:

const path = require('path');

app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, '/views'));

La prima riga di codice serve per importare il modulo path di Node JS, mentre le altre due righe di codice servono per configurare EJS come template engine di Express.

Quindi creiamo una cartella views e un file homepage.ejs all'interno di essa.

mkdir views
touch views/homepage.ejs (in Windows PowerShell usa il comando "New-Item" al posto di "touch")
<!DOCTYPE html>
<html lang="it">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Templating in Node JS</title>
</head>
<body>
  <h1>Benvenuto su EJS in Node JS</h1>
</body>
</html>

Ora che abbiamo creato il file homepage.ejs possiamo modificare il file index.js per renderlo funzionante.

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

app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, '/views'));

app.get('/', (req, res) => {
  res.render('homepage.ejs');
});

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

Come puoi notare abbiamo modificato la funzione che gestisce la richiesta alla homepage in modo che invece di ritornare una stringa ritorni il file homepage.ejs. Non c'è bisogno di specificare il percorso /views perchè abbiamo già detto ad Express che i file dei template si trovano in quella cartella.

Se hai il server già in esecuzione stoppalo e riavvialo altrimenti semplicemente avvia il server con il comando nodemon index.js e dopodichè andiamo a verificare che il tutto funzioni correttamente andando sul browser all'indirizzo http://localhost:3000 verificando che appunto la richiesta ci ritorna il contenuto del file homepage.ejs.

nodemon index.js

Con questo siamo appena riusciti a collegare correttamente EJS a Node JS ed a servire una richiesta HTTP con un template EJS! 🎉

Passare dati dinamici al template

Ora che abbiamo configurato correttamente EJS come template engine di Express e possiamo rendere correttamente una pagina HTML, sorge la domanda: come facciamo se volessimo passare in modo dinamico dei dati al template homepage.ejs ?

In questo momento gli unici contenuti che siamo in grado di visualizzare sono quelli che sono scritti in modo statico all'interno del file homepage.ejs ma andando avanti nelle lezioni vedremo come potremo connetterci ad un database e iniziare a giocare con tanti dati dinamici.

Quindi vediamo in che modo possiamo passare dei dati dal file index.js al template homepage.ejs.

La prima cosa che dobbiamo fare è modificare l'endpoint in index.js e passare un oggetto con i dati che appunto vogliamo passare al template.

Per ora proviamo a passare un nome ed una professione che poi visualizzeremo all'interno del template.

app.get('/', (req, res) => {
  res.render('homepage.ejs', { name: 'Emanuele', professione: 'Sviluppatore' } );
});

Ora che stiamo passando questo nome e professione al file homepage.ejs dobbiamo capire come poter utilizzare questi dati all'interno del template.

Per fare ciò dobbiamo utilizzare la sintassi di EJS all'interno del nostro codice HTML. Questa nuova sintassi può essere inizialmente un pò strana ma vedrai che dopo averla usata un paio di volte ti inizierà a diventare molto più semplice.

EJS mostra una sezione con i principali tags all'interno della documentazione ufficiale nella sezione "Tags": https://ejs.co/#install

Quello di cui noi abbiamo bisogno per visualizzare il nome e la professione è il tag <%= %> che ci permette di visualizzare il contenuto di una variabile all'interno del nostro template.

Quindi andiamo a modificare il file homepage.ejs in questo modo:

<!DOCTYPE html>
<html lang="it">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Templating in Node JS</title>
</head>
<body>
  <h1>Benvenuto su EJS in Node JS</h1>

  <p>Il mio nome è <%= name %> e sono <%= professione %></p>
</body>
</html>

Ora puoi anche provare a passare più dati, a creare nuovi endpoints e nuovi templates. In questo modo puoi iniziare a prendere confidenza con EJS e con il suo funzionamento.

Condizionali e Cicli in EJS

Condizionali

Oltre a poter passare dei dati dinamici al nostro template, EJS ci permette anche di utilizzare delle condizionali e dei cicli all'interno del nostro codice HTML.

Ad esempio proviamo ad usare un if statement per visualizzare un messaggio diverso in base al nome che abbiamo passato al template.

<!DOCTYPE html>
<html lang="it">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Templating in Node JS</title>
</head>
<body>
  <h1>Benvenuto su EJS in Node JS</h1>

  <% if (name === 'Emanuele') { %>
    <p>Il mio nome è <%= name %> e sono <%= professione %></p>
  <% } else { %>
    <p>Il mio nome non è Emanuele</p>
  <% } %>
</body>
</html>

Nota che la parte di codice che viene eseguita all'interno del nostro template è racchiusa tra i tag <% %> mentre la parte di codice che viene visualizzata all'interno del nostro template è racchiusa tra i tag <%= %>. C'è una differenza di un segno dell'uguale = tra i due tags. I tags <% %> senza il segno dell'uguale ci permettono di eseguire codice JavaScript senza farlo visualizzare nella pagina web, mentre utilizzando i due tags <%= %> ci permette di eseguire codice JavaScript e di dire al computer di visualizzare il risultato all'interno della pagina web.

Cicli

Oltre ai condizionali possiamo ovviamente anche utilizzare dei cicli all'interno del nostro template. Ad esempio proviamo a creare un array di nomi nel nostro endpoint e a visualizzarli all'interno del nostro template.

app.get('/', (req, res) => {
  const names = ['Emanuele', 'Marco', 'Luca', 'Giuseppe'];

  res.render('homepage.ejs', { names: names } );
});

Ora che abbiamo creato un array di nomi possiamo utilizzare un ciclo for all'interno del nostro template per visualizzare tutti i nomi all'interno della pagina web.

<!DOCTYPE html>
<html lang="it">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Templating in Node JS</title>
</head>
<body>
  <h1>Benvenuto su EJS in Node JS</h1>

  <% for (let i = 0; i < names.length; i++) { %>
    <p>Il mio nome è <%= names[i] %></p>
  <% } %>
</body>
</html>

Nota che abbiamo sostituito il codice del condizionale if statement con un ciclo for.

Il risultato nel browser sarà il seguente:

Conclusione

In questo articolo abbiamo visto come creare pagine web dinamiche con EJS in Node JS. Abbiamo visto come creare un semplice server con Express JS e configurarlo con EJS come template engine per creare dei template dinamici. Inoltre abbiamo visto come passare dei dati dinamici al nostro template e come utilizzare dei condizionali e dei cicli al suo interno.

Spero che la lezione sia stata di tuo gradimento! Preparati alla prossima lezione che ti introdurrà ad un altro concetto molto importante: le RESTful Routes! 🚀