Parcours Node.js / TypeScript
Confirmé
🎯 Objectif : construire des APIs Node.js modernes en TypeScript strict — choisir le bon framework selon le contexte, structurer un projet, valider, authentifier, tester.
À l'issue de cet axe, tu sauras :
- Choisir entre Hono, Fastify, Express 5, NestJS selon le projet
- Construire une API REST typée avec validation Zod et middleware
- Authentifier avec JWT en cookie HttpOnly
- Connecter une base de données via Drizzle ou Prisma 7
- Tester avec Vitest + Supertest sur une DB éphémère
Pourquoi Node.js en backend ?
Section intitulée « Pourquoi Node.js en backend ? »| Pour | Contre |
|---|---|
| Même langage que le frontend → partage de code (types, validation Zod, libs) | Mono-thread (workers ou multi-process pour le CPU-bound) |
| Excellent pour I/O-bound (APIs, streaming, temps réel) | Moins adapté aux calculs lourds (préférer Go/Rust/Python si besoin) |
| Écosystème npm gigantesque, Bun et Deno dispo en alternative | Complexité de l’écosystème (ESM/CJS, plein d’outils similaires) |
| TypeScript strict ≈ Java/C# en sécurité de typage, sans la cérémonie | Un projet bâclé se transforme vite en spaghetti |
Verdict 2026 : c’est le choix par défaut si ton frontend est en JS/TS, ou si tu fais du temps réel (WebSocket, SSE, edge).
Choisir son framework
Section intitulée « Choisir son framework »Hono — le défaut moderne (recommandé)
Section intitulée « Hono — le défaut moderne (recommandé) »| Style | Minimaliste, web standards (Request/Response du Fetch API) |
| TypeScript | Type-safe end-to-end, inférence excellente |
| Performance | Très rapide (~55 000 req/s sur Node, davantage sur Bun) |
| Cibles | Node, Bun, Deno, Cloudflare Workers, Vercel Edge, AWS Lambda |
| Écosystème | Middlewares pour CORS, JWT, logger, validateur Zod, etc. |
import { Hono } from 'hono';import { logger } from 'hono/logger';import { cors } from 'hono/cors';
const app = new Hono();app.use(logger(), cors());
app.get('/health', (c) => c.json({ status: 'ok' }));
app.get('/users/:id', (c) => { const id = c.req.param('id'); return c.json({ id, name: 'Alice' });});
export default app;Pourquoi Hono est devenu le défaut en 2026 : tu écris une fois, tu déploies sur n’importe quoi (Node serveur classique ou edge worker). Plus besoin de choisir au début entre Express et Cloudflare Workers.
Express 5 — la mature (legacy mais maintenue)
Section intitulée « Express 5 — la mature (legacy mais maintenue) »import express from 'express';
const app = express();app.use(express.json());
app.get('/health', (req, res) => res.json({ status: 'ok' }));
app.get('/users/:id', async (req, res) => { const user = await getUser(req.params.id); res.json(user);});
app.listen(3000);Express 5 (sortie stable fin 2024) apporte :
- Gestion async automatique (les exceptions dans les handlers async remontent au error middleware sans wrap manuel).
- Suppression d’APIs deprecated.
- Compatibilité avec Node 20+.
Quand le choisir : tu hérites d’un projet existant, ou tu veux la maturité maximum d’écosystème (énorme catalogue de middlewares).
Fastify — la performante classique
Section intitulée « Fastify — la performante classique »import Fastify from 'fastify';
const app = Fastify({ logger: true });
app.get('/users/:id', { schema: { params: { type: 'object', properties: { id: { type: 'string' } } }, response: { 200: { type: 'object', properties: { id: { type: 'string' }, name: { type: 'string' } } } }, },}, async (req) => { return { id: req.params.id, name: 'Alice' };});
await app.listen({ port: 3000 });Forces : ~3× plus rapide qu’Express, JSON Schema natif (validation + sérialisation rapides), plugins encapsulés (système d’extension propre).
Quand le choisir : APIs Node serveur classique avec exigence de perf, équipe qui n’a pas besoin de l’edge.
NestJS — pour les gros projets entreprise
Section intitulée « NestJS — pour les gros projets entreprise »import { Controller, Get, Param } from '@nestjs/common';
@Controller('users')export class UsersController { @Get(':id') findOne(@Param('id') id: string) { return { id, name: 'Alice' }; }}Forces : architecture imposée (modules, services, DI), décorateurs, intégrations avec presque tout (TypeORM, Prisma, GraphQL, microservices).
Faiblesses : verbeux, courbe d’apprentissage, sur-dimensionné pour les petits projets.
Quand le choisir : équipe 10+ devs, projet long-terme, équipes Java/Angular qui veulent retrouver leurs marques.
Tableau de décision
Section intitulée « Tableau de décision »| Si… | Choisis |
|---|---|
| Tu démarres un nouveau projet en 2026 | Hono |
| Tu vises l’edge (Cloudflare, Vercel) | Hono |
| Tu maintiens un Express existant | Express 5 (ne migre que si bénéfice clair) |
| Performance Node serveur, schema-driven | Fastify |
| Grosse équipe, structure imposée, architecture par modules | NestJS |
Structure de projet typique
Section intitulée « Structure de projet typique »Pour une API moyenne, voici une structure qui passe à l’échelle sans framework imposant :
taskly-api/├── src/│ ├── app.ts ← composition (middlewares + routes)│ ├── main.ts ← entry point (lance le serveur)│ ├── config.ts ← parsing des env via Zod│ ├── db/│ │ ├── schema.ts ← schémas Drizzle / Prisma│ │ └── index.ts ← client DB│ ├── modules/│ │ ├── auth/│ │ │ ├── auth.routes.ts│ │ │ ├── auth.service.ts│ │ │ └── auth.schemas.ts│ │ └── tasks/│ │ ├── tasks.routes.ts│ │ ├── tasks.service.ts│ │ └── tasks.schemas.ts│ ├── middleware/│ │ ├── auth.ts│ │ └── error.ts│ └── lib/│ ├── jwt.ts│ └── logger.ts├── tests/│ └── ...├── package.json├── tsconfig.json└── .env.exampleDécoupage par module métier (auth, tasks) plutôt que par couche technique (controllers/, services/). Plus facile à naviguer quand le projet grossit.
ORMs et accès DB
Section intitulée « ORMs et accès DB »| Outil | Style | Quand préférer |
|---|---|---|
| Drizzle | SQL-like, ESM, edge-compatible | Performance, edge deployment, contrôle SQL |
| Prisma 7 | Schema-first, migrations puissantes | Productivité, équipe pas SQL-experte |
| TypeORM | Decorators (NestJS-friendly) | Si déjà NestJS |
| Kysely | Query builder TypeScript pur | Type-safety extrême, pas d’ORM |
Prisma 7 — la nouveauté 2026
Section intitulée « Prisma 7 — la nouveauté 2026 »Prisma 7 a abandonné le moteur Rust pour un moteur TypeScript/WebAssembly. Conséquences :
- Bundle ~85 % plus léger (1.6 MB vs 11 MB).
- Performances ~3× meilleures sur grands résultats.
- Compatible edge (Cloudflare Workers).
// schema.prismamodel Task { id Int @id @default(autoincrement()) title String done Boolean @default(false) createdAt DateTime @default(now()) ownerId Int owner User @relation(fields: [ownerId], references: [id])}
// Code TSimport { PrismaClient } from '@prisma/client';const prisma = new PrismaClient();
const tasks = await prisma.task.findMany({ where: { done: false, ownerId: userId }, orderBy: { createdAt: 'desc' }, take: 20,});Drizzle — le challenger édge-first
Section intitulée « Drizzle — le challenger édge-first »import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core';
export const tasks = sqliteTable('tasks', { id: integer('id').primaryKey(), title: text('title').notNull(), done: integer('done', { mode: 'boolean' }).default(false), ownerId: integer('owner_id').notNull(), createdAt: text('created_at').default(sql`CURRENT_TIMESTAMP`),});
// Codeimport { db } from './db';import { eq } from 'drizzle-orm';
const tasks = await db .select() .from(tasks) .where(eq(tasks.ownerId, userId)) .orderBy(desc(tasks.createdAt)) .limit(20);✅ Plus proche du SQL → contrôle total. ✅ Bundle minuscule, edge-ready. ❌ Moins de magie : à toi d’écrire les jointures complexes.
Choix par défaut 2026 : Drizzle pour edge ou perfs ; Prisma 7 pour productivité maximale et migrations DSL.
Tests d’intégration
Section intitulée « Tests d’intégration »npm install -D vitest supertestimport { describe, it, expect, beforeEach } from 'vitest';import { app } from '../src/app';import { db } from '../src/db';
beforeEach(async () => { await db.delete(tasks); await db.insert(tasks).values([{ title: 'test', ownerId: 1 }]);});
describe('GET /tasks', () => { it('renvoie la liste', async () => { const res = await app.request('/tasks', { headers: { Authorization: 'Bearer test-token' }, }); expect(res.status).toBe(200); const data = await res.json(); expect(data.length).toBe(1); });});Avec Hono, app.request() te permet de tester sans démarrer un vrai serveur. Avec Express/Fastify, Supertest ou un simple fetch après listen().
Pour les tests bout-en-bout sur vraie DB : Testcontainers (lance un Postgres temporaire en Docker pour les tests). Robuste, mais lent.
Bun et Deno — alternatives à Node
Section intitulée « Bun et Deno — alternatives à Node »| Runtime | État 2026 | Quand l’envisager |
|---|---|---|
| Bun | Stable, plus rapide que Node, support npm, runtime+test+package manager unifiés | Projets greenfield qui veulent la perf |
| Deno | Stable, sécurité par défaut, TS natif, npm compat | Projets qui privilégient sécurité et standards |
| Node 24 | LTS, TS natif via type stripping depuis Node 24 | Le défaut universel, valeur sûre |
Hono (et beaucoup de libs modernes) tournent sur les trois runtimes sans modification.
Auto-évaluation
Section intitulée « Auto-évaluation »Pour aller plus loin
Section intitulée « Pour aller plus loin »- Hono Docs — hono.dev
- Express 5 Migration Guide — expressjs.com/en/guide/migrating-5.html
- Fastify Docs — fastify.dev
- NestJS Docs — docs.nestjs.com
- Prisma Docs — prisma.io/docs
- Drizzle ORM — orm.drizzle.team