[Tuto] Express.js le micro-framework pour Node.js

Node.js est trop bas niveau ? Vous voulez passer à la vitesse supérieure ? Ça tombe bien, je vais vous montrer Express.js un micro-framework pour Node.js qui vous fera gagner du temps.

Express.js va nous permettre gérer facilement les routes de notre application et d’utiliser un moteur de template pour nos vues.

Express.js a été adopté en production par de gros site comme :

Dans cet article, je vais vous présenter Express.js dans ça version 4 (sortie il y a quelque jour à l’heure où j’écris ses lignes) qui apporte multiples changements.

Installation

Il y a deux façons de démarrer un projet avec Express.js.

Premièrement en incluant une dépendance dans notre package.json suivi d’un npm install :

package.json :
{
    "name": "demo-express",
    "description": "demo express.js",
    "version": "0.0.1",
    "private": true,
    "dependencies": {
        "express": "4.x"
    }
}

Express.js sera disponible comme n’importe quel module, il vous suffit pour l’utiliser de faire un require :

app.js :
var express = require('express');
var app = express();

app.all('/', function(req, res){
    res.send('hello world');
});

app.listen(3000);

Deuxième façon, en demandant à Express.js de nous générer un projet de base. Pour cela il faut installer de façon globale express-generator :

> npm install -g express-generator

L’installation de façon globale d’express-generator va nous permettre d’utiliser des fonctionnalités de génération  de projet en ligne de commande. Pour vérifier la bonne installation d’express-generator faites :

> express --help

  Usage: express [options] [dir]

  Options:

    -h, --help          output usage information
    -V, --version       output the version number
    -e, --ejs           add ejs engine support (defaults to jade)
    -H, --hogan         add hogan.js engine support
    -c, --css   add stylesheet  support (less|stylus|compass) (defaults to plain css)
    -f, --force         force on non-empty directory

Nous allons utiliser express-generator pour nous générer les bases d’un projet. Pour cela entrez la commande express <nom_de_votre_projet> :

> express demo_express

Express.js nous a générer toute l’arborescence de notre projet dans un dossier demo_express, ainsi que les fichiers de bases :

  • /bin dossier contenant le serveur node.js
  • /node_modules dossier des modules
  • /public dossier des éléments accessible depuis le navigateur
    • /images dossier contenant les images
    • /javascripts dossier contenant les fichiers JS
    • /stylesheets dossier contenant les fichiers CSS
  • /routes dossier contenant les routeurs
  • /views dossier contenant les vues
  • app.js
  • package.json

Pour finir nous devons installer les dépendances de notre projet avec un npm install :

> npm install

Vous pouvez dors et déjà lancer le serveur Node.js :

> npm start

L’application est disponible en localhost sur le port 3000

Nous sommes maintenant fin prêts à commencer. Pour la suite de cet article j’ai utilisé la deuxième méthode qui a l’avantage d’avoir une base de projet prête.

Changer le moteur de template

Par défaut Express.js utile le moteur de template Jade. Je trouve ce langage de templating peu visible et difficilement maintenable, c’est pour cela que j’ai décider dont changer. Habituer au langage de templating de Symfony 2 twig, j’ai décidé d’utiliser Swig qui si rapproche. Si vous êtes plutôt habituer au JSP, je vous conseille EJS.

Pour changer de moteur de template commencez par supprimer Jade, pour cela entrez la commande suivante :

> npm rm jade

Supprimez également la dépendance Jade dans le package.json et ajoutez la dépendance Swig :

package.json :
...
"swig": "1.x"
...

Puis faite un npm install pour installer swig.

Ensuite, nous devons indiquer à Express.js d’utiliser Swig. Pour cela rendez-vous dans le fichier app.js.

Commencer par faire un require de swig :

app.js :
... 
var swig         = require('swig');
...

Supprimer les lignes suivantes qui correspondent à l’utilisation de Jade :

app.js :
... 
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
...

Enfin ajouter ses lignes pour indiquer à Express.js l’utilisation du moteur de template Swig :

app.js :
... 
// view engine setup
// utilisation du moteur de swig pour les .html
app.engine('html', swig.renderFile); 
// utiliser le moteur de template pour les .html
app.set('view engine', 'html'); 
// dossier des vues
app.set('views', path.join(__dirname, 'views')); 

// view cache
app.set('view cache', false); // désactivation du cache express
swig.setDefaults({ cache: false }); // désactivation du cache swig
...

Vous pouvez voir qu’il y a deux systèmes de cache pour les vues générer. Comme nous sommes en développement, ils sont désactives.

Nous avons maintenant le moteur de template Swig prêt qui se lancera sur les fichiers .html.

Ajouter une page

Pour tester Express.js nous allons ajouter une page de contact, nous ne feront pas l’envoi d’e-mail qui n’est pas le sujet de cet article.

Les routes

Express-generator nous a généré deux routeurs (/routes/index.js et /routes/users.js). Ces routeurs sont utilisés dans le fichier app.js :

app.js :
... 
var routes = require('./routes/index');
var users  = require('./routes/users');
...
app.use('/', routes);
app.use('/users', users);
...

Toutes les requêtes sont transmises au routeur index.js excepter les requêtes portant sur les URL « /users ». Cela permet de faire un découpage sémantique des routes d’une application (ex: pour un service Web REST).

Pour notre ajout de page, nous allons utiliser le routeur par défaut (index.js) car il s’agit d’une simple page du site.

/routes/index.js :
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res) {
  res.render('index', { title: 'Express' });
});

module.exports = router;

Nous voyons qu’il y a une route, la route vers la page home. Pour faire nos routes, il nous suffit d’utiliser la méthode router.VERBE(path, [callback…], callback). Le verbe correspond aux différentes méthodes HTTP (GET, POST, PUT, DELETE ).

Ajoutant nos deux routes, une pour le formulaire et l’autre pour le submit :

/routes/index.js :
...

/* GET contact page. */
router.get('/contact', function(req, res) {
    res.render('contact');
});

/* POST contact page (submit). */
router.post('/contact', function(req, res) {
    res.render('contact', { name: req.param('name') });
});

...

Nous pouvons voir que nos deux routes font appel à la méthode res.render(). Cette méthode permet la génération des vues avec le moteur de template que l’on a configuré tout à l’heure. Elle prend en paramètres le nom de la vue (ici contact) et éventuellement les paramètres pour la vue.

Pour la route du submit du formulaire de contact, nous transmettons à notre vue contact un paramètre POST nommé name avec la méthode req.param(<paramName>).

Les vues avec Swig

Pour nos vues, nous allons utiliser le framework CSS bootstrap 3 pour gagner du temps sur la mise en forme.

Avant de commencer notre vue contact, nous allons utiliser la puissance de notre moteur de template avec l’héritage pour créer un layout globale pour nos vues :

/views/layout.html :
<!DOCTYPE html>
<html>
<head>
    <title>Demo Express.js</title>
    <meta charset="UTF-8">
    <link href="/stylesheets/bootstrap.min.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="container">
    <header class="navbar navbar-default" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <a class="navbar-brand" href="/">Démo Express.js</a>
            </div>
            <div class="collapse navbar-collapse">
                {% include './include/nav.html' %}
            </div>
        </div>
    </header>

    {% block content %}{% endblock %}
</div>
</body>
</html>

Nous voyons ici deux éléments Swig, le premier {% include ‘./include/nav.html’ %} nous permet d’inclure du code. Ici nous incluons notre menu :

/views/include/nav.html :
<nav>
    <ul class="nav navbar-nav">
        <li><a href="/" title="Home">Home</a></li>
        <li><a href="/contact" title="Contact">Contact</a></li>
    </ul>
</nav>

Le deuxième élément {% block content %}{% endblock %} va nous permettre d’inclure notre contenu au bon endroit via l’héritage. Ce découpage permet d’éviter la redondance du code et une meilleure maintenabilité

Passons à notre vue contact :

/views/contact.html :
{% extends 'layout.html' %}

{% block content %}
<section class="container">
    {% if name %}
    <div class="alert alert-success alert-dismissable">
        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
        <strong>Well done!</strong> thank you for your <b>{{name}}</b> sends
    </div>
    {% endif %}

    <form role="form" action="/contact" method="post">
        <div class="form-group">
            <label for="email">Email</label>
            <input type="email" name="email" class="form-control" id="email" placeholder="Enter email">
        </div>
        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" name="name" class="form-control" id="name" placeholder="Enter name">
        </div>
        <div class="form-group">
            <label for="msg">Message</label>
            <textarea name="msg" class="form-control" id="msg" rows="3"></textarea>
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
    </form>
</section>
{% endblock %}

Vous pouvez voir que nous utilisons {% extends ‘layout.html’ %} pour hériter de notre layout et {% block content %}…{% endblock %} pour inclure du contenu dans notre block content.

Nous avons également une condition if avec {% if name %}…{% endif %}, qui teste la variable name. Si la variable name existe c’est que nous sommes à l’exécution du submit, nous affichons un message de succès ainsi que le nom saisie par l’utilisateur avec {{name}}.

form_contact
submit-contact

Conclusion

Nous avons vu comment gagner du temps avec le framework Express.js en générant les bases d’un projet, géré facilement les routes de notre application avec les routeurs et l’utilisation d’un moteur de template. Convaincu ? Sachez que je vous ai présenté que les principales fonctionnalités de Express.js et qu’il on reste de nombreuses autres.

Le code source de la démo est disponible sur mon Github ici.

4 réflexions au sujet de « [Tuto] Express.js le micro-framework pour Node.js »

    1. damienp Auteur de l’article

      Il faut que ton CSS soit dans un dossier « public ». Ce dossier va contenir tost tes fichiers statiques (images, CSS, etc) de ton site.
      Ensuite, il faut indiquer à express quel est ton dossier public dans app.js avec :

      
          app.use(express.static('/chemin-de-ton-dossier-publique'));
      

      Par défaut, si tu as utilisé l’express-generator le dossier publique est déjà configuré :

      
          app.use(express.static(path.join(__dirname, 'public')));
      

      Qui indique à express que le dossier contenant les fichiers statiques est /public.
      De plus, il génère un dossier pour tes CSS : /public/stylesheets.
      Il ne reste plus qu’à indiquer dans ton HTML ou se trouve ta feuille de style :

      
          <link href="/stylesheets/style.css" rel="stylesheet" type="text/css">
      

      Bonne continuation 😉

      Répondre

Laisser un commentaire