Débuter avec Express.js (Node)
Express.js est le framework web le plus populaire de l’écosystème Node.js. Là où le module http natif oblige à tout gérer à la main, Express fournit une couche légère et élégante pour définir des routes, traiter des requêtes et construire une API en quelques lignes. Minimaliste par philosophie, il n’impose presque rien et se laisse étendre par des milliers de modules. Ce guide vous fait construire un serveur Express de zéro : installation, routes, middlewares, lecture des données de requête, réponse en JSON, fichiers statiques, gestion d’erreurs et structure de projet.
Prérequis et installation
Express est un paquet Node : il vous faut Node.js installé et des bases de JavaScript côté serveur. Si ce terrain est neuf pour vous, notre guide Node.js pour débutants pose les fondations (runtime, modules, npm) sur lesquelles Express s’appuie.
Créez un dossier de projet, initialisez-le puis installez Express.
mkdir mon-api && cd mon-api
npm init -y
npm install express
Pour utiliser la syntaxe moderne import, ajoutez "type": "module" dans votre package.json.
Le serveur minimal
Voici l’application Express la plus simple : quelques lignes pour un serveur qui répond sur le port 3000.
import express from "express";
const app = express();
app.get("/", (req, res) => {
res.send("Bonjour depuis Express !");
});
app.listen(3000, () => {
console.log("Serveur démarré sur http://localhost:3000");
});
Lancez-le avec node index.js et ouvrez http://localhost:3000. Trois éléments à repérer : express() crée l’application, app.get() définit une route, et app.listen() met le serveur en écoute.
Les routes
Une route associe une méthode HTTP et un chemin à une fonction de traitement. Express fournit une méthode par verbe HTTP.
app.get("/articles", (req, res) => {
res.send("Liste des articles");
});
app.post("/articles", (req, res) => {
res.send("Article créé");
});
app.put("/articles/:id", (req, res) => {
res.send(`Article ${req.params.id} mis à jour`);
});
app.delete("/articles/:id", (req, res) => {
res.send(`Article ${req.params.id} supprimé`);
});
Ce découpage par verbe (GET, POST, PUT, DELETE) est exactement ce qui structure une API REST, que nous construisons plus bas.
Lire les données d’une requête : params, query, body
Une requête transporte des données de trois façons différentes, et Express les range dans trois objets distincts. Bien les distinguer évite beaucoup de confusion.
Les paramètres d’URL (req.params)
Les segments dynamiques du chemin, préfixés par :, se lisent dans req.params.
// GET /utilisateurs/42
app.get("/utilisateurs/:id", (req, res) => {
res.send(`Utilisateur demandé : ${req.params.id}`); // "42"
});
La chaîne de requête (req.query)
Ce qui suit le ? dans l’URL se lit dans req.query. Idéal pour la pagination, les filtres, la recherche.
// GET /recherche?terme=express&page=2
app.get("/recherche", (req, res) => {
const { terme, page } = req.query;
res.send(`Recherche « ${terme} », page ${page}`);
});
Le corps de la requête (req.body)
Les données envoyées dans le corps (un POST de formulaire ou de JSON) se lisent dans req.body. Attention : par défaut, req.body est undefined — il faut activer un middleware pour l’analyser (voir la section suivante).
app.post("/articles", (req, res) => {
const { titre, contenu } = req.body;
res.send(`Reçu : ${titre}`);
});
Les middlewares : le cœur d’Express
Un middleware est une fonction qui s’exécute entre la réception de la requête et l’envoi de la réponse. Elle reçoit req, res et une fonction next qu’elle doit appeler pour passer la main au middleware suivant. C’est le concept central d’Express : tout, ou presque, est un middleware.
// Middleware maison : journalise chaque requête
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next(); // indispensable, sinon la requête reste bloquée
});
Oublier next() est une erreur fréquente : sans lui, la requête ne progresse jamais et le client attend indéfiniment.
Le middleware le plus important à activer est celui qui analyse le JSON entrant. Sans lui, req.body reste vide sur les POST JSON.
app.use(express.json()); // analyse le JSON
app.use(express.urlencoded({ extended: true })); // analyse les formulaires HTML
On peut aussi appliquer un middleware à une seule route, par exemple pour vérifier une authentification.
function verifierAuth(req, res, next) {
if (!req.headers.authorization) {
return res.status(401).json({ erreur: "Non authentifié" });
}
next();
}
app.get("/prive", verifierAuth, (req, res) => {
res.json({ message: "Contenu réservé" });
});
Servir du JSON : construire une API REST
C’est l’usage phare d’Express. La méthode res.json() sérialise automatiquement un objet JavaScript et positionne le bon en-tête Content-Type. Voici une petite API CRUD en mémoire.
let articles = [
{ id: 1, titre: "Débuter avec Express" },
{ id: 2, titre: "Comprendre les middlewares" },
];
// Lister
app.get("/api/articles", (req, res) => {
res.json(articles);
});
// Récupérer un élément
app.get("/api/articles/:id", (req, res) => {
const article = articles.find(a => a.id === Number(req.params.id));
if (!article) {
return res.status(404).json({ erreur: "Introuvable" });
}
res.json(article);
});
// Créer
app.post("/api/articles", (req, res) => {
const nouveau = { id: Date.now(), titre: req.body.titre };
articles.push(nouveau);
res.status(201).json(nouveau); // 201 = créé
});
Notez l’usage de res.status() pour fixer le code HTTP : 200 par défaut, 201 pour une création, 404 pour une ressource absente. Un code de statut correct fait partie d’une API propre.
Servir des fichiers statiques
Pour livrer des fichiers directement — HTML, CSS, images, JavaScript client —, le middleware express.static pointe vers un dossier. Tout ce qu’il contient devient accessible par URL.
// Le contenu du dossier "public" est servi tel quel
app.use(express.static("public"));
// public/style.css → http://localhost:3000/style.css
// public/index.html → http://localhost:3000/
La gestion des erreurs
Express reconnaît un middleware d’erreur à sa signature à quatre paramètres : (err, req, res, next). Placé en dernier, après toutes les routes, il centralise le traitement des erreurs.
// Route qui déclenche une erreur
app.get("/plante", (req, res, next) => {
try {
throw new Error("Quelque chose a échoué");
} catch (err) {
next(err); // on transmet l'erreur au gestionnaire
}
});
// Gestionnaire d'erreurs (toujours en dernier, 4 arguments)
app.use((err, req, res, next) => {
console.error(err.message);
res.status(500).json({ erreur: "Erreur interne du serveur" });
});
Ajoutez aussi une route « attrape-tout » pour les chemins inconnus, renvoyant un propre 404.
// Après toutes les routes valides
app.use((req, res) => {
res.status(404).json({ erreur: "Route introuvable" });
});
Structurer un projet Express
Un seul fichier suffit pour apprendre, mais un vrai projet se découpe. La convention courante sépare les routes dans des modules grâce au Router d’Express.
// routes/articles.js
import { Router } from "express";
const router = Router();
router.get("/", (req, res) => res.json({ message: "Tous les articles" }));
router.get("/:id", (req, res) => res.json({ id: req.params.id }));
export default router;
// index.js
import express from "express";
import articlesRouter from "./routes/articles.js";
const app = express();
app.use(express.json());
// Toutes les routes du module sont préfixées par /api/articles
app.use("/api/articles", articlesRouter);
app.listen(3000);
Une organisation typique sépare routes/ (définition des chemins), controllers/ (la logique), et middlewares/ (fonctions transverses). Cette séparation garde le code lisible à mesure que l’API grandit.
À retenir
Express structure un serveur Node autour de trois idées : les routes (app.get, app.post… selon le verbe HTTP), les middlewares (fonctions en chaîne reliées par next()), et les objets req/res pour lire la requête et construire la réponse. Distinguez req.params (segments d’URL), req.query (après le ?) et req.body (corps, à activer avec express.json()). Pour une API, répondez avec res.json() et le bon res.status(). Enfin, placez toujours le middleware d’erreur à quatre arguments en dernier. Avec ces briques, vous tenez une API REST fonctionnelle et bien structurée.