Node.js Framework

Express

Express est le framework web Node.js minimaliste et non-opinionné. Une route, une fonction et une chaîne de middleware : voilà tout le modèle mental, et pourtant, il propulse encore une immense partie du web.

beginner16 min readUpdated 16 sept. 2026
server.js
js
// server.js
import express from "express";

const app = express();
app.use(express.json());

app.get("/users/:id", async (req, res, next) => {
  try {
    const user = await db.user.findById(req.params.id);
    if (!user) return res.status(404).json({ error: "not_found" });
    res.json(user);
  } catch (err) {
    next(err);
  }
});

app.listen(3000);
Sortie
2010
S'exécute sur
Node.js
Style
Minimaliste, non-opinionné
Idée centrale
Chaîne de middleware
Langage
JavaScript / TypeScript
Version
5.x

Pourquoi c'est important

Pourquoi Express est encore partout

Un routage sans cérémonie

Définissez vos points de terminaison avec app.get, app.post et consorts. Les chemins peuvent être statiques, paramétrés ou basés sur des motifs, et les gestionnaires restent de simples fonctions.

Du middleware pour tout

L'authentification, la journalisation, le parsing et la validation ne sont que des fonctions dans une chaîne. Composez de petits modules plutôt que de configurer un framework massif.

Un écosystème colossal

Des milliers de packages de middleware et des années de retours d'expérience signifient que presque chaque problème possède déjà une solution légère et éprouvée.

Le tableau complet

Les trois idées fondamentales d'Express

Une route correspond à une URL, un gestionnaire reçoit la requête et la réponse, et le middleware enveloppe tout le reste.

Routage

Correspondance

Une méthode et un chemin sélectionnent le gestionnaire à exécuter. Les routes peuvent être regroupées dans des routers et montées sous un préfixe.

Middleware

Composition

Les fonctions reçoivent (req, res, next) et soit terminent la réponse, soit passent le contrôle à la suite de la chaîne.

Requête & Réponse

Échange

De fines couches d'abstraction sur les objets HTTP de Node — lisez l'entrée, définissez le statut et les headers, et envoyez un corps de réponse.

HTML5 en un coup d'oeil

Ce que vous obtenez concrètement

Routes

app.get("/posts/:id") correspond à une URL et exécute un gestionnaire.

Middleware

app.use(fn) s'exécute avant ou après les routes, selon l'ordre d'enregistrement.

req et res

Lisez les paramètres, la query et le body ; définissez le statut et envoyez du JSON ou des fichiers.

Routers

express.Router() permet de garder les applications volumineuses modulaires et montables.

Middleware d'erreur

Une fonction à quatre arguments centralise les réponses d'erreur.

Middleware de sécurité

helmet, cors et les limites de débit (rate limits) s'intègrent en une seule ligne.

Un bref aperçu

D'un jouet inspiré de Sinatra à un standard du web

  1. 2010

    Naissance d'Express

    TJ Holowaychuk publie un petit framework inspiré de Sinatra (Ruby).

    10
  2. 2011

    Middleware Connect

    Express absorbe le modèle de middleware de Connect, ce qui définira son API pendant des années.

    11
  3. 2014

    Express 4

    Le router est réécrit et le middleware est dissocié dans des packages séparés.

    14
  4. 2016

    L'ère de la gouvernance ouverte

    La gestion par IBM et StrongLoop permet à Express d'être maintenu alors que Node croît.

    16
  5. 2024

    Express 5

    Une version majeure attendue depuis longtemps apporte la gestion des erreurs asynchrones et une base moderne.

    24

Le guide complet

Express: Tout ce que vous devez savoir

Qu’est-ce qu’Express ?

Express est un framework web minimaliste pour Node.js. Il ne vous impose ni structure de dossiers, ni base de données, ni architecture. Il vous fournit trois éléments essentiels et vous laisse ensuite libre de vos choix : un moyen de faire correspondre des URLs, un objet requête (request) et un objet réponse (response), ainsi qu’une chaîne de middleware pour lier le tout.

Cette sobriété est volontaire. Express est apparu en 2010, à une époque où le module http natif de Node nécessitait d’écrire manuellement le routage et l’analyse du corps des requêtes (body parsing). Express a réduit ces tâches à quelques lignes de code. Quinze ans plus tard, il reste le choix par défaut pour les API Node, et ses concepts ont été repris par presque tous les frameworks qui ont suivi.

Si vous comprenez Express, vous comprenez la structure même du JavaScript côté serveur.

Le cycle requête-réponse

Dans son essence, une application Express est une fonction qui reçoit une requête et envoie une réponse. Tout le reste n’est que du sucre syntaxique pour faciliter le développement.

import express from "express";

const app = express();

app.get("/", (req, res) => {
  res.send("Hello, world");
});

L’objet req encapsule le message entrant de Node.js : req.params, req.query, req.body et req.headers vous fournissent les données d’entrée. L’objet res encapsule le message sortant : res.status(), res.json(), res.send() et res.set() façonnent la sortie. Un handler met fin à la requête en appelant l’une des méthodes res.

Routage

Une route est composée d’une méthode, d’un chemin et d’un ou plusieurs handlers. Les chemins peuvent être statiques, paramétrés avec :name, ou correspondre à des patterns.

app.get("/posts", listPosts);
app.get("/posts/:id", getPost);
app.post("/posts", createPost);
app.put("/posts/:id", replacePost);
app.patch("/posts/:id", updatePost);
app.delete("/posts/:id", deletePost);

Les paramètres de route arrivent dans req.params, et les query strings dans req.query.

app.get("/posts/:id", (req, res) => {
  const { id } = req.params;          // "/posts/42" -> "42"
  const { fields } = req.query;       // "?fields=title" -> "title"
  res.json({ id, fields });
});

Vous pouvez également passer plusieurs handlers à une seule route. Ils s’exécutent dans l’ordre jusqu’à ce que l’un d’entre eux termine la réponse ; c’est ainsi que vous attachez des middleware par route, comme la validation ou l’autorisation.

app.post("/posts", requireAuth, validatePost, createPost);

Middleware : le concept essentiel à maîtriser

Le middleware est le cœur d’Express. Il s’agit de toute fonction qui reçoit (req, res, next) et qui, soit termine la réponse, soit appelle next() pour continuer.

function logger(req, res, next) {
  const start = Date.now();
  res.on("finish", () => {
    console.log(`${req.method} ${req.url} ${res.statusCode} ${Date.now() - start}ms`);
  });
  next();
}

app.use(logger);

Le middleware s’exécute dans l’ordre où il est enregistré. Cette règle unique explique la majeure partie du comportement d’Express : enregistrez le parseur JSON avant les routes qui lisent req.body, enregistrez l’authentification avant les routes protégées, et enregistrez le gestionnaire de 404 après toutes les autres routes.

Il existe trois types qu’il est utile de connaître :

  • Application middlewareapp.use(fn) s’exécute pour chaque requête.
  • Router middlewarerouter.use(fn) s’exécute uniquement pour les chemins de ce routeur.
  • Route middlewareapp.get(path, fn, handler) s’exécute uniquement pour cette route.

Un middleware qui prend quatre arguments est un error handler et ne s’exécute que lorsqu’une fonction appelle next(err).

Les routeurs permettent de garder les applications volumineuses lisibles

À mesure qu’une application s’agrandit, un fichier unique de routes devient ingérable. express.Router() vous permet de regrouper les routes liées et de les monter sous un préfixe.

// routes/posts.js
import { Router } from "express";

const router = Router();

router.get("/", listPosts);
router.post("/", createPost);

export default router;
// app.js
import posts from "./routes/posts.js";

app.use("/api/v1/posts", posts);

Désormais, chaque fichier gère une seule ressource, et le préfixe d’URL est défini à un seul endroit. C’est cette structure qui empêche les projets Express de se transformer en un amas d’endpoints.

Gestion des erreurs

Les erreurs doivent converger vers un point unique. Appelez next(err) depuis n’importe où et Express sautera directement au premier gestionnaire d’erreurs à quatre arguments.

app.get("/users/:id", async (req, res, next) => {
  try {
    const user = await db.user.findById(req.params.id);
    if (!user) return res.status(404).json({ error: "not_found" });
    res.json(user);
  } catch (err) {
    next(err);
  }
});
app.use((err, req, res, next) => {
  console.error(err);
  res.status(err.status ?? 500).json({
    error: err.code ?? "internal_error",
    message: err.message,
  });
});

Express 5 transfère automatiquement les promesses rejetées vers le gestionnaire d’erreurs, les gestionnaires async n’ont donc plus besoin d’un wrapper. Cependant, être explicite avec try/catch rend l’intention évidente et permet de garder le code portable. Enregistrez un gestionnaire 404 après toutes les routes afin que les chemins non correspondants retournent une erreur JSON appropriée au lieu de la page HTML par défaut d’Express.

Lire le corps de la requête

Express ne parse pas les corps de requête par défaut. Ajoutez les parsers intégrés avant les routes qui en ont besoin.

app.use(express.json());                        // application/json
app.use(express.urlencoded({ extended: true })); // form posts

Pour l’upload de fichiers, utilisez multer. Pour une validation plus poussée, combinez le parsing avec une bibliothèque de schémas comme Zod ou Joi afin de rejeter les entrées invalides rapidement, avant qu’elles n’atteignent vos handlers.

Bases de la sécurité et de la production

Express est volontairement minimaliste, ainsi, quelques lignes de middleware permettent de couvrir l’essentiel :

import helmet from "helmet";
import cors from "cors";
import rateLimit from "express-rate-limit";

app.use(helmet());                 // sensible security headers
app.use(cors({ origin: "https://app.example.com" }));
app.use(rateLimit({ windowMs: 60_000, max: 100 }));

Désactivez également x-powered-by, maintenez vos dépendances à jour, validez et limitez la taille des requêtes, et ne faites jamais confiance aux entrées du client. Ce sont les mêmes préoccupations pour tout backend ; Express vous offre simplement un endroit restreint et bien connu pour gérer chacun de ces points.

Tests

Comme les handlers sont de simples fonctions, Express est facile à tester. supertest démarre l’application dans le processus actuel et permet d’effectuer de réelles assertions HTTP sans ouvrir de port.

import request from "supertest";
import app from "../app.js";

test("GET /posts returns a list", async () => {
  const res = await request(app).get("/posts").expect(200);
  expect(Array.isArray(res.body)).toBe(true);
});

Séparez la définition de l’application (app.js) du démarrage du serveur (server.js) afin que les tests puissent importer l’application sans lancer l’écoute. Cette simple séparation rend les tests d’intégration triviaux.

Bonnes pratiques

  • Gardez vos route handlers légers ; déplacez la logique dans des services et des couches d’accès aux données.
  • Divisez vos routes par fonctionnalité avec express.Router() et montez-les sous un préfixe de version.
  • Enregistrez vos middleware de manière réfléchie et dans l’ordre : les parsers, puis l’auth, puis les routes, puis le 404, et enfin les erreurs.
  • Transmettez chaque erreur avec next(err) et formatez les réponses à un seul endroit.
  • Validez et limitez toutes les entrées avant qu’elles n’atteignent la logique métier.
  • Utilisez helmet, cors et le rate limiting dès le premier jour.
  • Séparez l’application du serveur pour que les tests restent rapides.

Erreurs courantes

  • Oublier express.json() et se demander pourquoi req.body est undefined.
  • Négliger les promesses rejetées dans les handlers async sur Express 4.
  • Enregistrer le handler 404 ou le gestionnaire d’erreurs avant les routes qu’ils sont censés intercepter.
  • Laisser un seul fichier de routes s’étendre sur des centaines de lignes.
  • Retourner un code 200 pour des erreurs au lieu d’utiliser les codes de statut appropriés.
  • Faire confiance à req.body sans validation.
  • Mélanger res.send, res.json et res.end de manière imprévisible.

Et après ?

Express vous a enseigné le fonctionnement des requêtes, des réponses et de la chaîne de middleware — des concepts que vous réutiliserez tout au long de votre carrière. Si vous recherchez plus de performance et une validation intégrée, consultez ensuite le guide Fastify. Si vous avez besoin de structure et d’injection de dépendances pour une équipe nombreuse, tournez-vous vers NestJS. Pour les déploiements edge et serverless, Hono propose le même style sur un runtime basé sur les standards du web. Et si tout cela vous a semblé aller trop vite, n’hésitez pas à revoir les bases de Node.js qui sous-tendent tout ceci.

En pratique

Une app, quatre composants

Basculez entre les éléments pour voir comment ils s'imbriquent.

server.js
import express from "express";
import routes from "./routes.js";

const app = express();

app.use(express.json());
app.use("/api", routes);

app.listen(3000, () => console.log("http://localhost:3000"));

Gestion des erreurs asynchrones

Express 5 transmet automatiquement les promesses rejetées, mais être explicite reste plus clair et fonctionne de la même manière dans toutes les versions.

Préférer
router.get("/posts", async (req, res, next) => {
  try {
    const posts = await Post.find();
    res.json(posts);
  } catch (err) {
    next(err);
  }
});
Éviter
router.get("/posts", async (req, res) => {
  const posts = await Post.find();
  res.json(posts);
  // rejection is silently lost in Express 4
});

Ordre des middleware

Le middleware s'exécute dans l'ordre d'enregistrement ; le parser et l'auth doivent donc être montés avant les routes qui en dépendent.

Préférer
app.use(express.json());
app.use(auth);
app.use("/api", routes);
app.use(notFound);
app.use(onError);
Éviter
app.use("/api", routes);
app.use(express.json());
app.use(auth);
// body is undefined inside routes

Compromis

Express est-il le bon choix par défaut ?

Express privilégie la familiarité et la simplicité. Connaissez le coût avant de passer à l'échelle.

Strengths

  • Aucun prérequis d'apprentissage

    L'API est minuscule, la documentation est excellente, et presque tout développeur Node peut lire une app Express dès le premier jour.

  • Un écosystème inégalé

    L'authentification, les uploads, les sessions, la validation et la journalisation disposent tous de middleware matures et éprouvés en production.

  • Vous gardez le contrôle

    Il n'y a pas de structure cachée. Vous choisissez l'organisation des dossiers, la base de données et les patterns au lieu de subir les opinions d'un framework.

Trade-offs

  • C'est à vous de créer les conventions

    Sans structure commune, les grandes apps Express dérivent vers des gestionnaires incohérents. Une organisation claire est plus cruciale ici que dans les frameworks opinionnés.

  • Performances bonnes, mais pas exceptionnelles

    Express est assez rapide pour la plupart des services, mais Fastify et Node brut peuvent gérer nettement plus de requêtes par seconde.

  • Les erreurs asynchrones sont faciles à manquer

    Dans Express 4, une promesse rejetée est silencieusement ignorée. Même en version 5, un try/catch ou un next(err) permet de garder les échecs visibles.

FAQ

Foire aux questions

Keep learning

Related topics from the roadmap.

$ commencer à apprendre

Prêt à apprendre Express ?

Notre tutoriel interactif vous guide à travers Express pas à pas — avec des quiz et du vrai code que vous pouvez exécuter dans le navigateur.