
Utilisation de moteurs de template (EJS, Pug, Handlebars)
Apprenez a utiliser les moteurs de template EJS, Pug et Handlebars avec Express.js (app.set, res.render) pour generer dynamiquement des pages HTML cote serveur.
Le besoin de generer du HTML dynamique
Nous avons vu comment envoyer des réponses JSON avec `res.json()` et comment servir des fichiers HTML statiques avec `res.sendFile()` ou `express.static()`. Cependant, la plupart des applications web ne se contentent pas de servir des pages statiques. Elles ont besoin de générer des pages HTML dont le contenu varie en fonction des données spécifiques à la requête, à l'utilisateur connecté, ou à l'état de l'application (par exemple, afficher une liste de produits personnalisée, le profil d'un utilisateur, ou un message de bienvenue nominatif).
Construire ces pages HTML dynamiques en concaténant des chaînes de caractères dans nos gestionnaires de routes Express deviendrait rapidement un cauchemar en termes de lisibilité, de maintenabilité et de sécurité (risque d'injection XSS si les données ne sont pas correctement échappées). Il nous faut une approche plus structurée pour séparer la logique de récupération des données de la logique de présentation (le HTML).
C'est précisément le rôle des moteurs de template (template engines). Ce sont des outils conçus pour prendre un fichier "modèle" (le template), qui contient la structure HTML de base et des marqueurs spéciaux, et de le combiner avec des données dynamiques fournies par votre application Node.js pour générer la page HTML finale qui sera envoyée au client.
Comprendre les moteurs de template et `res.render()`
Un moteur de template fonctionne sur le principe de la séparation des préoccupations :
- Votre code Node.js/Express (le contrôleur) est responsable de récupérer les données nécessaires (depuis une base de données, une API externe, etc.).
- Le fichier template (la vue) est responsable de définir la structure HTML et d'indiquer où et comment afficher les données dynamiques reçues du contrôleur.
Express.js s'intègre facilement avec de nombreux moteurs de template populaires. La configuration se fait généralement via la méthode `app.set()` :
- `app.set('view engine', 'nom_du_moteur')` : Indique à Express quel moteur de template utiliser par défaut (ex: 'ejs', 'pug', 'hbs'). Vous devrez d'abord installer le package npm correspondant au moteur choisi.
- `app.set('views', chemin_vers_les_templates)` : Spécifie le répertoire où Express doit chercher les fichiers de template (par défaut, un dossier nommé `views` à la racine du projet). Le module `path` est souvent utilisé pour construire ce chemin de manière fiable : `app.set('views', path.join(__dirname, 'views'))`.
Une fois configuré, la méthode clé pour utiliser le moteur de template est `res.render(viewName, [locals])` :
- `viewName` (String) : Le nom du fichier de template à utiliser (par exemple, `'profile'`, `'product-list'`). Express cherchera ce fichier dans le répertoire `views` configuré et ajoutera automatiquement l'extension associée au moteur de template (ex: `.ejs`, `.pug`, `.hbs`).
- `locals` (Object, optionnel) : Un objet JavaScript dont les propriétés contiennent les données que vous souhaitez rendre disponibles dans le template. Les clés de cet objet deviennent les variables accessibles dans le fichier template.
Lorsque vous appelez `res.render()`, Express charge le fichier template spécifié, le traite avec le moteur de template configuré en lui passant les données `locals`, puis envoie le HTML résultant comme réponse au client, en définissant automatiquement le `Content-Type` à `text/html`.
Tour d'horizon de moteurs populaires : EJS, Pug, Handlebars
Il existe de nombreux moteurs de template pour Node.js, chacun avec sa propre syntaxe et philosophie. Voici trois des plus populaires :
1. EJS (Embedded JavaScript Templating)
- Philosophie : Permet d'intégrer du JavaScript standard directement dans votre HTML en utilisant des délimiteurs spéciaux.
- Syntaxe Clé :
<% code JavaScript %>: Exécute du code JavaScript (boucles, conditions...).<%= variable %>: Injecte la valeur de `variable` dans le HTML en l'échappant (sécurisé contre XSS).<%- variable %>: Injecte la valeur de `variable` sans l'échapper (utile pour injecter du HTML brut, mais potentiellement dangereux si la source n'est pas fiable).
- Avantages : Très facile à apprendre si vous connaissez déjà JavaScript et HTML. Flexible.
- Installation :
npm install ejs - Configuration :
app.set('view engine', 'ejs'); - Exemple (`views/index.ejs`) :
<%= title %> <%= heading %>
-
<% items.forEach(item => { %>
- <%= item %> <% }); %>
- Appel :
app.get('/', (req, res) => { res.render('index', { title: 'Ma Page EJS', heading: 'Liste de choses', items: ['Pomme', 'Banane', 'Orange'] }); });
2. Pug (anciennement Jade)
- Philosophie : Utilise une syntaxe basée sur l'indentation, sensible aux espaces, pour générer du HTML de manière très concise. Pas de balises fermantes explicites.
- Syntaxe Clé : L'indentation définit la structure. Les noms de balises sont suivis d'attributs entre parenthèses et de contenu après un espace. Utilise `=` pour le contenu échappé et `!=` pour le contenu non échappé. Supporte mixins, héritage de layout, etc.
- Avantages : Templates très courts, propres et lisibles une fois la syntaxe maîtrisée. Force une bonne structure.
- Inconvénients : Courbe d'apprentissage, la syntaxe basée sur l'indentation peut être source d'erreurs si l'on n'est pas rigoureux.
- Installation :
npm install pug - Configuration :
app.set('view engine', 'pug'); - Exemple (`views/layout.pug` et `views/index.pug` - héritage) :
// layout.pug doctype html html head title= pageTitle body block content // Bloc où le contenu spécifique sera inséré // index.pug extends layout.pug // Hérite de layout.pug block content h1= heading ul each item in items li= item - Appel :
app.get('/', (req, res) => { res.render('index', { pageTitle: 'Ma Page Pug', heading: 'Ma Liste', items: ['Un', 'Deux', 'Trois'] }); });
3. Handlebars
- Philosophie : Syntaxe inspirée de Mustache, utilisant des doubles accolades `{{ }}` pour l'interpolation. Vise une séparation plus stricte entre logique et présentation, en limitant la logique dans les templates.
- Syntaxe Clé :
{{variable}}: Injecte la valeur de `variable` en l'échappant.{{{variable}}}: Injecte la valeur sans l'échapper (triple accolade).- Structures de contrôle limitées (
{{#if condition}}...{{/if}},{{#each collection}}...{{/each}}) et utilisation de "helpers" pour la logique plus complexe.
- Avantages : Syntaxe claire, séparation logique/présentation encouragée, nombreux helpers disponibles, très populaire.
- Inconvénients : Moins de flexibilité logique directement dans le template que EJS.
- Installation :
npm install express-handlebars handlebars(express-handlebarsfacilite l'intégration) - Configuration (avec `express-handlebars`) :
const { engine } = require('express-handlebars'); app.engine('hbs', engine({ extname: '.hbs', defaultLayout: 'main'})); // .hbs comme extension app.set('view engine', 'hbs'); app.set('views', './views'); // Répertoire des vues - Exemple (`views/layouts/main.hbs` et `views/home.hbs`) :
// layouts/main.hbs (layout principal){{pageTitle}} {{{body}}} // home.hbs (vue spécifique){{heading}}
-
{{#each items}}
- {{this}} {{/each}}
- Appel :
app.get('/', (req, res) => { res.render('home', { // Note: ne pas inclure l'extension .hbs pageTitle: 'Accueil Handlebars', heading: 'Mes Eléments', items: ['Alpha', 'Beta', 'Gamma'] // 'layout: false' peut être ajouté pour désactiver le layout par défaut }); });
Choisir son moteur et conclusion
Le choix entre EJS, Pug, Handlebars ou d'autres moteurs dépend largement des préférences de l'équipe et des besoins spécifiques du projet. EJS est souvent choisi pour sa familiarité avec JavaScript. Pug séduit par sa concision, tandis que Handlebars est apprécié pour sa simplicité syntaxique et sa séparation plus stricte.
Quel que soit le moteur choisi, l'utilisation de `app.set()` pour la configuration et de `res.render()` pour générer les vues est le mécanisme standard dans Express. Les moteurs de template sont des outils indispensables pour construire des applications web rendues côté serveur (Server-Side Rendering - SSR) avec Node.js et Express, permettant de générer du HTML dynamique de manière organisée, maintenable et efficace.