Apprendre Express.js : Moteur de Template Pug

Composant essentiel de tout framework web, le moteur de template permet d'isoler proprement la partie interface de votre application. Zoom sur Pug.

IcĂŽne de calendrier
Intermédiaire
8 chapitres

Qu’est-ce qu’un moteur de templates ?

DĂ©finition

Les moteurs de templates, ou “moteurs de modĂšles” sont des langages qui permettent de gĂ©nĂ©rer dynamiquement du HTML.

Vous pouvez ainsi dĂ©finir des templates pour votre application, qui peuvent ensuite ĂȘtre remplis dynamiquement avec des donnĂ©es provenant de votre base de donnĂ©es ou d’autres sources de donnĂ©es.

Ce dynamisme est rendu possible via de nombreuses fonctionnalités, notamment algorithmiques :

  • Variables ;
  • Structures conditionnelles (if, else if, else, switch) ;
  • Structures itĂ©ratives (each, for, while
) ;
  • Inclusions ;
  • HĂ©ritage de template ;
  • Etc.

L’utilisation d’un moteur de template est gĂ©nĂ©ralement considĂ©rĂ©e comme essentielle dans un framework web, car elle permet de sĂ©parer clairement le code logique de l’application de la prĂ©sentation visuelle de l’interface.

Principaux moteurs de templates

Du cĂŽtĂ© de Node.js et d’Express, on fait souvent rĂ©fĂ©rence Ă  :

  1. Pug ;
  2. Ejs ;
  3. Handlebars ;
  4. Hogan ;
  5. Twig (implémentation JavaScript du célÚbre moteur de template PHP #symfony) ;
  6. Etc.

IntĂ©ressons-nous de plus prĂšs au plus cĂ©lĂšbre d’entre eux, j’ai nommĂ© Pug !

Pug : la référence Node.js

Anciennement connu sous le nom de « Jade », ce moteur de template a été renommé « Pug » suite à des problÚmes juridiques.

Pug est un moteur de templates implémenté en JavaScript dont la syntaxe minimaliste est inspirée de Haml.

Un template Pug est un fichier portant l’extension .pug, basĂ©e sur une syntaxe proche des sĂ©lecteurs CSS (et par extension des raccourcis Emmet).

copié !
section#about
	h2 About me
	.grid
		.col-4
			img(src='https://picsum.photos/500', alt='Image de démonstration')
		.col-8
			p Paragraphe 1
			p Paragraphe 2

Cet extrait Pug correspond au HTML suivant :

copié !
<section id="about">
	<h2>About me</h2>
	<div class="grid">
		<div class="col-4">
			<img src="https://picsum.photos/500" alt="Image de démonstration">
		</div>
		<div class="col-8">
			<p>Paragraphe 1</p>
			<p>Paragraphe 2</p>
		</div>
	</div>
</section>

Voici les grands points Ă  retenir :

IndentationL’indentation indique l’imbrication / la hiĂ©rarchie entre les Ă©lĂ©ments. Il est important de ne pas mĂ©langer espaces et tabulations.
Raccourcis (sélecteurs CSS)On crée des éléments à la maniÚre des sélections CSS : p pour <p></p>, #about pour id="about", .grid pour class="grid", img(src='https://monsite.com/img/demo.png', alt='Image de démonstration') pour <img src="https://monsite.com/img/demo.png" alt="Image de démonstration">
Écrire du texteLe premier espace notĂ© derriĂšre une balise HTML indique que le contenu qui suit est du texte. p Paragraphe 1 pour <p>Paragraphe 1</p>

Installation de Pug

Comme tout paquet, pug est téléchargeable via votre gestionnaire de paquet favori. Voici la commande npm :

copié !
npm install pug

Initialisation de Pug

Une fois installĂ©, il est important d’initialiser Pug dans votre application Express, sans quoi il ne serait pas exploitable.

Utiliser la méthode app.set() afin de définir le moteur de template à utiliser :

app.js
copié !
app.set('view engine', 'pug');

Par dĂ©faut, les templates Pug seront Ă  placer dans le dossier 📁 views, situĂ© Ă  la racine du projet. Si vous souhaitez travailler avec un autre rĂ©pertoire de vues, vous avez la possibilitĂ© de dĂ©finir ce dernier en utilisant une nouvelle fois la mĂ©thode app.set().

app.js
copié !
app.set('views', './templates');

On dĂ©finit ici le dossier 📁 templates comme Ă©tant celui qui contiendra nos templates Pug.

Avec le module path

Il n’est pas rare de voir des extraits de projet Node / Express exploitant le module path. Ce module propose tout un tas de mĂ©thodes utiles pour travailler avec des chemins.

copié !
const path = require('path');

app.set('views', path.join(__dirname, 'templates'));

Dynamiser ses templates

Comme tout moteur de template digne de ce nom, Pug implĂ©mente des structures dynamiques telles que les variables, la notion d’hĂ©ritage et d’inclusion, des boucles et des conditions.

Variables

La plupart du temps, on utilise dans les templates des variables transmises par l’application (rĂ©cupĂ©ration d’élĂ©ments en base de donnĂ©es), mais nous avons parfois besoin, dans un souci algorithmique, d’en dĂ©clarer directement dans nos templates.

DĂ©claration

La dĂ©claration d’une variable se fait avec le mot clĂ© var :

copié !
- var msg = "Hello world!";
- var tva = 0.2;
- var fruits = ["Pomme", "Poire", "Banane"];

Affichage

Il est aisĂ© d’afficher des variables transmises par l’application (au niveau des routes) ou dĂ©clarĂ© directement dans nos templates.

Affichage du contenu de la variable uniquement avec =

copié !
h1= title
p= message

Affichage interpolé (concaténé) avec #{}

copié !
p Publié par #{author}

Ecriture dans un attribut HTML (sans les guillemets "")

copié !
img(src=article.image, alt="Blablabla...")

HĂ©ritage

Pug prend en charge l’hĂ©ritage de templates.

Cela signifie qu’au sein d’un template, il est possible de spĂ©cifier des zones, appelĂ©es blocs, dans lesquelles un template enfant va pouvoir injecter du contenu.

  • Ces zones de contenu dynamiques se dĂ©clarent avec le mot-clĂ© block.
  • Pour spĂ©cifier qu’un template hĂ©rite d’un autre, on utilise le mot-clĂ© extends.

Parent

layout.pug
copié !
doctype html
html
	head
		title #{title} - Nom du site
		meta(charset='UTF-8')
	body
		include includes/_header.pug
		block content
		include includes/_footer.pug

Enfant

copié !
extends layout.pug

block content
	section.section.is-dark
		h1= title
		p Lorem ipsum dolor sit amet...

Il est Ă©galement possible de dĂ©finir un contenu par dĂ©faut dans un bloc parent. Ce contenu s’affichera si le template enfant ne vient pas insĂ©rer du contenu au sein du bloc en question.

copié !
block content
	p Paragraphe par défaut

Inclusions

Les inclusions permettent d’intĂ©grer des templates dans d’autres templates.

Ceci est trÚs utile pour intégrer des composants communs (= partials) appelés plusieurs fois comme des headers, footers, sidebars, etc., ou encore pour les isoler. Cela permet entre autres de respecter le principe du DRY (Dont Repeat Yourself).

Une inclusion s’effectue avec le mot-clĂ© include en spĂ©cifiant en suivant le chemin vers le fichier.

layout.pug
copié !
html
	head
	body
		include includes/_header.pug
		main
		include includes/_footer.pug

Ici on va chercher les fichiers 📄 views/includes/_header.pug et 📄 views/includes/_footer.pug.

Boucles

Pug propose deux types de boucles : each et while.

Each

La boucle each est trĂšs utile pour boucler sur des objets (provenant gĂ©nĂ©ralement de l’application) afin d’en afficher les caractĂ©ristiques.

copié !
section.products
	h1 Produits
	each product in products
		article.product
			img(src=product.image, alt=product.alt)
			h2= product.title
			p= product.description
	else
		p Aucun produits...

Voici le HTML généré :

copié !
<section class="products">
	<h1>Produits</h1>
	<article class="product">
		<img src="/img/produit1.png" alt="Produit 1">
		<h2>Produit 1</h2>
		<p>Description du produit...</p>
	</article>
	<article class="product">
		<img src="/img/produit2.png" alt="Produit 2">
		<h2>Produit 2</h2>
		<p>Description du produit...</p>
	</article>
	...
</div>

While

La boucle while est quant Ă  elle trĂšs utile dans des problĂ©matiques plus algorithmiques (calculs, etc), ou du moins pour des boucles pour lesquelles on ne connaĂźt pas Ă  l’avance le nombre d’itĂ©rations Ă  effectuer.

copié !
- var n = 0;
ul
	while n < 3
		li= n++

Voici le HTML généré :

copié !
<ul>
	<li>0</li>
	<li>1</li>
	<li>2</li>
</ul>

Conditions (if, else if et else)

Comme tout moteur de template digne de ce nom, Pug dispose d’un systùme de conditions si - sinon si - sinon. En voici quelques exemples :

copié !
if user.authenticated
	a(href='https://monsite.com/logout') logout
else
	a(href='https://monsite.com/login') login
copié !
if student.note < 8
	p Refusé.
else if student.note >= 8 && student.note <MdxCode 10
	p Rattrapage.
else
	p Admis.

Vous pourrez Ă©galement retrouver l’équivalent switch sur la documentation officielle.

Retourner un template Pug

Pour retourner un template, il faut se placer dans une route de l’application et retourner avec la mĂ©thode res.render() le template Pug en question.

copié !
app.get('/contact', function (req, res) {
	res.render('contact', { title: 'Contact', message: 'Une question ? Contactez-moi via ce formulaire !' })
});