Lorsque j'ai construit ma première API de production, j'ai utilisé Express.js et la configuration a pris environ deux heures : code répétitif, middleware, gestionnaires de routes, configuration TypeScript et scripts de déploiement. Récemment, j'ai livré une API REST complète en seulement 20 minutes avec NitroJs. Pas de chaînes app.use(), pas de routage manuel, pas de maux de tête de déploiement.
Ce guide vous montre comment NitroJs élimine le code répétitif tout en vous offrant un backend prêt pour la production qui fonctionne partout : Node, Bun, Deno, serverless ou edge.
Qu'est-ce que NitroJs et pourquoi l'utiliser pour les API backend ?
NitroJs est une boîte à outils serveur de l'écosystème UnJS qui traite votre backend comme un artefact de build. Au lieu d'écrire un serveur qui se couple à un runtime, vous écrivez des gestionnaires de routes et Nitro les compile en un bundle portable. Déployez le même code sur Node.js, Cloudflare Workers, Vercel ou un conteneur Docker sans changer une ligne.

Modèle mental central : Écrivez des routes, pas des serveurs. Vous vous concentrez sur la logique de l'API ; Nitro gère HTTP, le middleware et le liant de plateforme.
Avantages clés pour les API backend :
- Zéro configuration : Pas de code répétitif
server.js - Routage par système de fichiers :
routes/users.get.tsdevientGET /users - TypeScript natif : Types auto-inférés à partir des gestionnaires
- Déploiement universel : Une seule build, plusieurs cibles
- Mise en cache intégrée : Stockez les réponses de l'API en mémoire, Redis ou Cloudflare KV
- Couche de stockage : Système de fichiers abstrait pour les données temporaires
Pour les développeurs d'API, cela signifie que vous livrez plus rapidement et refactorez moins lors des changements d'infrastructure.
Démarrage rapide : Installez NitroJs en 5 minutes
Étape 1 : Initialiser un projet
# Using pnpm (recommended)
pnpm dlx giget@latest nitro nitro-api-backend
# Or npm
npm create nitro@latest nitro-api-backend
# Or bun
bunx giget@latest nitro nitro-api-backend
Ceci clone le modèle de démarrage officiel dans nitro-api-backend.
Étape 2 : Explorer la structure
cd nitro-api-backend
tree -L 2
Sortie :
├── server
│ ├── api
│ ├── routes
│ ├── tasks
│ └── middleware
├── nitro.config.ts
├── package.json
└── tsconfig.json
Répertoires critiques :
server/api/: Routes d'API (sans interface utilisateur)server/routes/: Routes full-stack (pour SSR)server/middleware/: Middleware globalserver/tasks/: Tâches d'arrière-plan
Pour une API backend pure, ignorez routes et mettez tout dans api.
Étape 3 : Exécuter le serveur de développement
pnpm install
pnpm dev
Nitro démarre sur http://localhost:3000 avec rechargement à chaud. Modifiez un fichier et le serveur redémarre en moins de 200 ms.

Construire votre premier point d'API
Gestionnaire GET simple
Créez server/api/users.get.ts :
// server/api/users.get.ts
export default defineEventHandler(() => {
return [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" }
];
});
Nitro sert automatiquement cela à GET /api/users. L'enveloppe defineEventHandler assure la sécurité des types et l'accès au contexte de la requête.
Route dynamique avec paramètres
Créez server/api/users/[id].get.ts :
// server/api/users/[id].get.ts
export default defineEventHandler((event) => {
const id = getRouterParam(event, 'id');
if (!id) {
throw createError({
statusCode: 400,
statusMessage: 'User ID is required'
});
}
return {
id: Number(id),
name: `User ${id}`,
email: `user${id}@example.com`
};
});
Accédez à GET /api/users/42 pour voir { id: 42, name: "User 42", ... }.
Requête POST avec corps JSON
Créez server/api/users.post.ts :
// server/api/users.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody(event);
// Nitro parses JSON automatically
const { name, email } = body;
if (!name || !email) {
throw createError({
statusCode: 422,
statusMessage: 'Name and email are required'
});
}
// Simulate database insertion
const newUser = {
id: Math.floor(Math.random() * 1000),
name,
email,
createdAt: new Date().toISOString()
};
return newUser;
});
Testez-le :
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"Charlie","email":"charlie@example.com"}'
Réponses typées
Nitro infère les types de réponses à partir de vos valeurs de retour. Pour des contrats stricts, utilisez des types explicites :
// server/api/products.get.ts
interface Product {
id: number;
name: string;
price: number;
inStock: boolean;
}
export default defineEventHandler<Product[]>(() => {
return [
{ id: 1, name: "Laptop", price: 1299.99, inStock: true },
{ id: 2, name: "Mouse", price: 29.99, inStock: false }
];
});
Désormais, les clients important ce point d'accès bénéficient d'un IntelliSense complet.
Modèles d'API avancés
Middleware pour l'authentification
Créez server/middleware/auth.ts :
// server/middleware/auth.ts
export default defineEventHandler(async (event) => {
const protectedRoutes = ['/api/admin', '/api/users/me'];
if (protectedRoutes.some(route => event.path.startsWith(route))) {
const token = getHeader(event, 'authorization')?.replace('Bearer ', '');
if (!token || token !== process.env.API_SECRET) {
throw createError({
statusCode: 401,
statusMessage: 'Unauthorized'
});
}
}
});
Le middleware s'exécute avant chaque route. Ajoutez-le à nitro.config.ts :
// nitro.config.ts
export default defineNitroConfig({
srcDir: 'server',
runtimeConfig: {
apiSecret: process.env.API_SECRET
}
});
Mise en cache des réponses d'API
Mettez en cache les calculs coûteux pendant 60 secondes :
// server/api/stats.get.ts
export default defineCachedEventHandler(async () => {
const db = useStorage('data');
const users = await db.getItem('users') || [];
return {
totalUsers: users.length,
activeUsers: users.filter(u => u.lastSeen > Date.now() - 86400000).length
};
}, {
maxAge: 60, // seconds
name: 'stats',
getKey: () => 'global-stats'
});
Nitro gère l'invalidation du cache et le stockage (mémoire, Redis ou Cloudflare KV selon la cible de déploiement).
Gestion des téléversements de fichiers
// server/api/upload.post.ts
export default defineEventHandler(async (event) => {
const files = await readMultipartFormData(event);
if (!files?.length) {
throw createError({ statusCode: 400, statusMessage: 'No files uploaded' });
}
const storage = useStorage('uploads');
const file = files[0];
await storage.setItem(file.filename, file.data);
return { success: true, filename: file.filename };
});
Testez avec :
curl -X POST http://localhost:3000/api/upload \
-F "file=@/path/to/image.jpg"
Déploiement : Du local à la production
Build pour la production
pnpm build
Nitro génère un répertoire .output avec des points d'entrée spécifiques à la plateforme.
Exécuter sur Node.js
node .output/server/index.mjs
Aucun node_modules requis – la build regroupe tout.
Déployer sur Cloudflare Workers
# Install preset
pnpm add -D nitro-preset-cloudflare-workers
# Build with preset
NITRO_PRESET=cloudflare-workers pnpm build
# Deploy
wrangler deploy .output
Déployer sur Vercel (Serverless)
# Vercel detects Nitro automatically
vercel
Ou configurez nitro.config.ts :
export default defineNitroConfig({
preset: 'vercel-edge'
});
Variables d'environnement
Créez .env localement, puis utilisez les tableaux de bord de la plateforme en production :
# .env
API_SECRET=dev-secret-key
DATABASE_URL=file:./dev.db
Accès dans les gestionnaires :
const config = useRuntimeConfig();
const secret = config.apiSecret;
Cas d'utilisation avancés
WebSockets et Server-Sent Events
Nitro prend en charge les WebSockets via defineWebSocketHandler :
// server/api/ws.ts
export default defineWebSocketHandler({
open(peer) {
console.log('WebSocket connected:', peer);
},
message(peer, message) {
peer.send(`Echo: ${message.text()}`);
},
close(peer, details) {
console.log('WebSocket closed:', details);
}
});
Accédez à ws://localhost:3000/api/ws.
Tâches d'arrière-plan
Créez server/tasks/cleanup.ts :
// server/tasks/cleanup.ts
export default defineCronHandler('0 2 * * *', async () => {
const db = useStorage('temp');
const keys = await db.getKeys();
for (const key of keys) {
const metadata = await db.getMeta(key);
if (metadata.expiresAt < Date.now()) {
await db.removeItem(key);
}
}
console.log('Cleanup completed');
});
Ceci s'exécute quotidiennement à 2h du matin. Déployez sur une plateforme avec support cron (par exemple, Vercel, Netlify).
Moteurs de workflow
Intégrez avec useWorkflow.dev pour une orchestration complexe :
// server/api/workflows/process.ts
import { createWorkflow } from '@useworkflow/sdk';
export default defineEventHandler(async (event) => {
const workflow = createWorkflow('data-pipeline', {
steps: [
{ id: 'fetch', run: 'https://api.example.com/data' },
{ id: 'transform', run: 'transform.js' },
{ id: 'store', run: async (data) => {
const storage = useStorage('results');
await storage.setItem('latest', data);
}}
]
});
await workflow.start();
return { status: 'started' };
});
Scénarios réels de développeurs
Scénario 1 : Backend de site statique
Déployez une API Nitro sur Cloudflare Workers qui sert des données JSON à un site JAMstack statique. Le niveau gratuit gère 100 000 requêtes/jour.
Scénario 2 : API d'application mobile
Créez des points d'accès REST pour une application React Native. Utilisez la gestion CORS intégrée de Nitro :
// nitro.config.ts
export default defineNitroConfig({
routeRules: {
'/api/**': { cors: true }
}
});
Scénario 3 : Passerelle de microservices
Exécutez Nitro comme une passerelle API qui agrège les microservices. Utilisez $fetch pour proxifier les requêtes :
// server/api/aggregate.get.ts
export default defineEventHandler(async (event) => {
const [users, posts] = await Promise.all([
$fetch('https://users-service.internal/users'),
$fetch('https://posts-service.internal/posts')
]);
return { users, posts };
});
Testez vos API NitroJs avec Apidog
Nitro génère des backends rapidement, mais la vitesse ne signifie rien si vos points d'accès tombent en panne. Lorsque vous livrez un nouveau POST /api/users, importez la définition de la route dans Apidog. Il fait de la rétro-ingénierie du type de retour de votre gestionnaire et génère automatiquement des tests de contrat.

Exécutez-les en CI pour détecter les changements cassants avant que votre équipe frontend ne s'arrache les cheveux. C'est gratuit pour commencer, et c'est le garde-fou dont votre développement rapide avec Nitro a besoin.
Questions fréquemment posées
1. Nitro peut-il remplacer complètement Express.js ?
Oui. Nitro gère mieux le routage, le middleware et le déploiement. Migrez en déplaçant le middleware Express vers les plugins Nitro et les routes vers server/api/.
2. Comment Nitro gère-t-il les connexions à la base de données ?
Utilisez les plugins Nitro pour initialiser les pools au démarrage. La couche de stockage abstrait la mise en cache, mais pour SQL, utilisez votre propre ORM (Prisma, Drizzle).
3. Nitro est-il prêt pour la production ?
Absolument. Nuxt utilise Nitro pour des millions de sites en production. Il est éprouvé pour l'échelle.
4. Puis-je utiliser Nitro avec GraphQL ?
Oui. Ajoutez un gestionnaire GraphQL dans server/api/graphql.post.ts. Utilisez n'importe quelle bibliothèque GraphQL Node – Nitro ne vous restreint pas.
5. Quelle est la différence entre Nitro et Hono ?
Hono est un routeur léger. Nitro est une boîte à outils serveur complète avec des builds, des préréglages et du stockage. Utilisez Hono pour les microservices, Nitro pour les backends complets.
Conclusion
NitroJs repense le développement backend en compilant votre API en un artefact portable. Vous obtenez un routage par système de fichiers, la sécurité TypeScript et un déploiement universel sans code répétitif. Créez votre prochaine API REST avec Nitro et validez-la avec Apidog. Votre futur vous remerciera lorsque vous migrerez de Node vers le edge en une seule ligne de configuration.
