Formation Express JS | Intégrer le Moteur de Template Pug avec Express JS

Explorez Pug, un moteur de template puissant pour créer des interfaces web claires et structurées au sein de vos applications Node/Express.

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 !' })
});