NodeJS+Haml e Pug

Avevo intenzione di scrivere un articolo su come usare Haml e Sass partendo dal progetto base con Node, ma mi sono reso conto che il pacchetto per utilizzare Haml all’interno di Node non è molto aggiornato e quindi ho deciso di fare comunque un accenno a quel pacchetto e poi usarne un altro. Quindi inizio con Haml e poi proseguirò con Pug.

Haml

Haml è l’acronimo di HTML Abstraction Markup Language. Per quello che può interessarvi e per essere chiari e diretti, Haml vi permette di scrivere codice HTML in modo più rapido e in un certo senso più ordinato.
Più rapido perché effettivamente, grazie a Haml potrete scrivere meno codice e ottenere lo stesso risultato che otterrete scrivendo del normale HTML.
Più pulito perchè Haml vi obbliga a tenere il vostro codice ben indentato e questo crea quindi del codice più leggibile (in quanto se non lo farete, Haml vi segnala l’errore).

Facciamo subito qualche esempio rapido. Immaginate di avere un div con all’interno un altro div. In HTML scrivereste così:

<div>
<div>
Prova
</div>
</div>

Volendo potereste anche scrivere tutto su un’unica riga e funzionerebbe lo stesso. 
In Haml la stessa cosa la scrivereste così:

%div
%div
= "Prova"

Bello vero? Molto meno codice e con l’obbligo di indentarlo. Come potete vedere non esistono i tag di chiusura. Haml capisce quando deve chiudere un tag grazie all’indentazione. Quindi il primo div è a livello “0” di indentazione. Il secondo è a livello “1”, quindi vuol dire che sarà all’interno del primo. Il testo è a livello “2” e quindi vorrà dire che sarà all’interno del secondo div. Tutto qui, veramente molto semplice.

Andiamo avanti. Pensate di voler aggiungere una classe, un id, o un attributo al vostro tag. Ecco qui come fare:

%div.myClass
%div#myId
%div{"data-info": "test"}

E il risultato del codice HTML generato sarà questo:

<div class="myClass"></div>
<div id="myId"></div>
<div data-info="test"></div>

Probabilmente all’inizio questo modo di scrivere non vi sarà subito chiaro, ma basta veramente poco per capirlo e metterselo bene in testa.

A questo link potete trovare più di informazioni riguardo a Haml:

Gli esempi che troverete su questo sito si basano su Ruby, ma la logica e il funzionamento è circa lo stesso di quello che andrete a vedere fra poco.

Haml.js

Haml.js è il pacchetto che vi viene in aiuto per riuscire a visualizzare file “.haml” all’interno del vostro server. Grazie a Haml.js sarete in grado di scrivere file in Haml e di fare in modo che il vostro server li visualizzi come se fossero dei normali file HTML.

La prima cosa da cosa fare, subito dopo aver creato un progetto base, è quindi quella di installare Haml.js. Per farlo basta quindi lanciare questo comando da terminale:

$ npm install hamljs -S

A questo punto potete aprire il vostro file che gestirà il server e impostare Haml come template engine per le vostre pagine. 
Il vostro codice dovrebbe essere questo:

const express = require("express");
const haml = require("hamljs");
const port = 3000;
const ip = "0.0.0.0";
const app = express();

app.set("views", "views");
app.engine('.haml', require('hamljs').renderFile);
app.set("view engine", "haml");

app.use(express.static('public'))

app.get("/", function(req, res)
{
res.render("index");
})
const server = app.listen(port, ip, function()
{
console.log("server started on "+ip+":"+port);
})

Gran parte del codice scritto sopra dovrebbe esservi familiare. Viene impostato un server utilizzando Express. A parte aver richiesto “hamljs”, le novità più importanti in questo caso sono due. 
La prima è quella che trovate in queste righe:

app.set("views", "views");
app.engine('.haml', require('hamljs').renderFile);
app.set("view engine", "haml");

Quello che state facendo queste righe è questo:

  • State dicendo a Express che i file di “vista” (quindi le pagine che mostrerete ai nostri visitatori) si troveranno all’interno della cartella “views” (il primo “views” indica il nome della proprietà che state impostando e il secondo indica il nome della cartella in cui salverete i vostri file “.haml”).
  • State dicendo a Express che per visualizzare i file “.haml” dovrà utilizzare il pacchetto “hamljs” che avete installato.
  • State dicendo a Express che per “renderizzare” (visualizzare) i file dovrà utilizzare come template engine, quello chiamato “haml”.

Grazie a queste tre righe Express sarà in grado di visualizzare i vostri file “.haml” come normali file HTML. Almeno dovrebbe. C’è un però un problema con le versioni di Express dalla 3 in poi. Per risolverlo dovrete scaricare il pacchetto consolidate, includerlo nel vostro file “index.js” e poi cambiare in questo modo la seconda riga dell’ultimo blocco scritto:

app.engine('.haml', cons.haml);

Per installare consolidate il comando è il solito:

npm install consolidate -S

e ricordatevi di fare un require e mettere il risultato all’interno di una costante chiamata cons (o scegliete un altro nome che preferite):

const cons = require("consolidate");

A questo punto il vostro file “index.js” sarà leggermente cambiato e dovrà essere così:

const express = require("express");
const haml = require("hamljs");
const cons = require("consolidate");
const port = 3000;
const ip = "0.0.0.0";
const app = express();

app.set("views", "views");
app.engine('.haml', cons.haml);
app.set("view engine", "haml");

app.use(express.static('public'))

app.get("/", function(req, res)
{
res.render("index");
})

const server = app.listen(port, ip, function()
{
console.log("server started on "+ip+":"+port);
})

In questo modo avete risolto la prima “novità” importante. Se vi ricordate le novità però erano due. La seconda è questa:

res.render("index");

In questa riga state dicendo che volete far visualizzare ai vostri utenti non più una semplice scritta o un semplice file, ma volete che venga renderizzato (quindi nel nostro caso convertito da Haml a HTML) il file chiamato “index” (l’estensione non è necessaria ma il file deve essere un “.haml”) che troveremo nella root della cartella che avete impostato come cartella per le “views”. Quindi in questo caso verrà renderizzato il file chiamato “index.haml” che si trova all’interno della cartella “views”.
Bene, ci siete quasi, manca solo la parte più facile. Quale? Non avete ancora creato il file “index.haml”. Quindi come detto prima, create il file all’interno della cartella “views” (o se avete usato un altro nome della cartella, usate il nome che avete utilizzato) e scrivete questo:

!!!
%html
%head
%meta{content: "width=device-width, initial-scale=1", name: "viewport"}
%link{href: "./css/style.css", media: "all", rel: "stylesheet", type: "text/css"}
%meta{charset: "UTF-8"}
%body
%script{src: "js/main.js"}

Forse il codice sopra vi può sembrare un po’ complesso e contorto, ma è semplice codice Haml!
Ho incluso già uno stile CSS e un file JS (salvati rispettivamente in “public/css/style.css” e “public/js/main.js”.
L’unica parte strana potrebbero essere quei 3 punti esclamativi iniziali. Haml.js convertirà quei 3 punti esclamativi in questo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

e così anche il vostro !DOCTYPE è a posto.

A questo punto direi che potete far partire il vostro server e collegandovi all’indirizzo: http://127.0.0.1:3000/ dovreste riuscire a vedere la vostra pagina.

L’ultima cosa che vorrei mostrarvi di Haml è la possibilità di scrivere degli script all’interno del vostro file “.haml”. Provate a creare una nuova pagina chiamata “test.haml” e provate a scrivere questo all’interno del tag body della vostra pagina (attenti all’indentazione):

%body
- totLines = 20;
%ul
- for(var i = 0; i < totLines; i++)
%li
= "Pos" + i

E voilà! Avete creato una variabile e l’avete utilizzata per gestire un ciclo! 
Ovviamente questo potrebbe tornarvi utile quando dovete riscrivere la stessa cosa più volte o anche quando dovrete visualizzare un array che proviene dal server. Ma come fare a passare variabili dal server alla vostra pagina? Anche questo è veramente molto semplice. Iniziate con il creare un array con alcuni nomi e inseritelo subito dopo la definizione della costante app:

var names = [];
names.push("Giovanni");
names.push("Antonio");
names.push("Maria");

Per passare delle variabili alle vostre pagine, il metodo render prevede un oggetto come secondo parametro dove all’interno potete aggiungere quante variabili volete (coppia nome proprietà e valore). Nel vostro caso potreste scrivere così per passare dei parametri alla vostra pagina “test.haml”:

res.render("test", {players: names});

La variabile names sarà quindi passata alla vostra pagina e raggiungibile con il nome “players”. Provate quindi a visualizzare i nomi dei giocatori grazie a un ciclo for:

- for(var i = 0; i < players.length; i++)
%li
= players[i]

e se volete potete usare anche questa tecnica per ciclare gli elementi all’interno del vostro array:

- each name in players
%li
= name

o ancora:

- each name, index in players
%li
= index + " - " + name

Come vedete quindi Haml può risultare molto comodo e vi può tornare molto utile ancheper la visualizzazione di dati dinamici.

Riassumendo: Haml vi tornerà utile per scrivere codice più rapido, pulito e dinamico!

Pug

C’è però un piccolo problema che ho riscontrato usando Haml.js: non c’è modo di includere parti di una pagina all’interno di un’altra. Immaginate di avere varie pagine tutte con delle stesse parti di codice, per esempio le intestazioni iniziali e magari il footer del vostro sito. Ecco, dovreste riscrivere ogni volta queste parti, per ogni pagina (o almeno io non ho trovato soluzioni facili per farlo… forse una ma è leggermente complessa e non penso abbia senso spiegarla). Servirebbe quindi un modo di includere delle pagina all’interno di altre. O meglio, servirebbe qualcosa per potere gestire dei partial, ossia delle “parti di pagina”. Purtroppo questa funzionalità non è stata implementata all’interno di Haml.js e, oltre a questo, Haml.js non è più aggiornato ormai da qualche anno. Quindi… vi ho spiegato tutto questo per niente!? La risposta ovviamente è no. Prima di tutto potete comunque usare Haml con altri linguaggi, non solo all’interno di Node. Per poter usare Haml all’interno di Node e avere anche altre funzionalità esiste un altro pacchetto che sfrutta la stessa logica che avete imparato finora. Questo pacchetto si chiama Pug (prima chiamato Jade) e questo è il repository ufficiale:

Installate quindi questo nuovo pacchetto:

npm install pug -S

E impostata il motore di rendering non più con haml, ma con pug:

const pug = require("pug");
...
app.engine('.haml', cons.pug);
app.set("view engine", "pug");

e create un nuovo file nella cartella “views” e chiamatelo “test.pug”. Dovrete copiare il codice che avevate prima in “index.haml” ma con alcuni accorgimenti. Questo è il codice finale:

doctype transitional
html
head
meta(content= "width=device-width, initial-scale=1", name= "viewport")
link(href= "./css/style.css", media= "all", rel= "stylesheet", type= "text/css")
meta(charset= "UTF-8")
body
- totLines = 20;
ul
- for(var i = 0; i < players.length; i++)
li
= players[i]
each name in players
li
= name
each name, index in players
li
= index + " - " + name
script(src= "js/main.js")

E questi gli accorgimenti:

  • Al posto di !!! per il !DOCTYPE, dovrete usare doctype transitional (o altri tipi di !DOCTYPE predefiniti: https://pugjs.org/language/doctype.html).
  • Non dovete più usare il simbolo % prima dei tag.
  • Quando dovete aggiungere degli attributi a un tag, non dovete usare le parentesi graffe ma dovete usare quelle tonde. Per assegnare un valore a una proprietà di un attributo dovrete usare il simbolo = e non più i :.
  • Quando usate il comando each non dovete più iniziare la riga con -. Questo perché dovete usare il - solamente quando scriverete del codice javascript (come ad esempio il ciclo for). L’each usato come nell’esempio, non è un comando di javascript, ma è un comando interno a Pug.

Questi e altri accorgimenti potete trovarli tutti a questo link:

Pug rimane quindi un’alternativa a Haml.js. Certo, ci sono delle piccole differenze ma di base sfrutta la stessa logica dell’importanza dell’indentazione e della non chiusura dei tag. Permette quindi di essere più veloci e puliti nello scrivere codice, proprio come se stessimo usando codice scritto in Haml.
Ovviamente Pug risolve anche il problema della gestione dei partial, non presente in Haml.js. Per farlo usa il comando include, seguito dal percorso del file, quindi in questo modo:

include percorso/nomeFile

Potete quindi finalmente modificare il vostro progetto creando un file per le intestazioni iniziali della vostra pagina HTML che andrete poi a includere nel file “test.pug” e in una nuova copia del file “index.haml”, ma convertito in pug (quindi “index.pug”).
Create quindi una cartella chiamata “partials” e all’interno create il file per la vostra header e chiamatelo “header.pug”. Il codice potrebbe essere questo:

doctype transitional
html
head
meta(content= "width=device-width, initial-scale=1", name= "viewport")
link(href= "./css/style.css", media= "all", rel= "stylesheet", type= "text/css")
meta(charset= "UTF-8")
body

A questo punto andate a includere la vostra header all’interno di “index.html” e “test.html”, in questo modo:

include partials/header.pug
= "Index pug!"
script(src= "js/main.js")

e

include partials/header.pug
= "Test pug!"
- totLines = 20;
ul
- for(var i = 0; i < players.length; i++)
li
= players[i]
each name in players
li
= name
each name, index in players
li
= index + " - " + name
script(src= "js/main.js")

Per ora è tutto. In questo modo potrete sfruttare la tecnica di Haml con le funzionalità di Pug!

Like what you read? Give Mauro a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.