Déploiement
Déploiement • Chapitre 2 : Préparation d'un projet avant le déploiement

Configuration des scripts de démarrage

Les plateformes de déploiement (Render, Railway, Heroku, AWS) n'ont pas d'yeux humains : elles interagissent avec votre projet via un contrat standardisé de scripts dans package.json. Si vos scripts build et start sont mal configurés, votre déploiement échouera à la dernière seconde.

🏗️
Script "build"

Compile le code TypeScript vers du JavaScript pur et minifié dans un répertoire de sortie (dist/ ou build/).

🚀
Script "start"

Invoque directement le binaire node sur les fichiers compilés. Ne jamais exécuter d'outils de dev ici.

🔌
L'IP 0.0.0.0 & PORT

Le serveur doit impérativement écouter sur process.env.PORT et l'adresse universelle 0.0.0.0 (pas localhost).

🛡️
Arrêt Propre (SIGTERM)

Intercepter le signal de terminaison pour fermer les connexions SQL sans couper les requêtes en vol.

Générateur de Scripts package.json Prêts pour la Production

Générateur Interactif

Sélectionnez votre type de projet pour obtenir la configuration standard attendue par les hébergeurs :

API Node.js (TypeScript)

Compile d'abord les sources TS avec tsc ou esbuild, puis exécute le binaire JS natif produit.

Piège fatal évité : N'utilisez JAMAIS "ts-node" ou "nodemon" dans le script start en production ! Ils consomment une mémoire énorme pour observer les fichiers et recompilent à chaque requête.
Commande de build :npm run build
Commande de run :node dist/main.js
package.json ("scripts")
{
  "scripts": {
    "dev": "nodemon --exec ts-node src/main.ts",
    "prebuild": "rimraf dist",
    "build": "tsc -p tsconfig.build.json",
    "prestart": "npm run db:migrate",
    "start": "node dist/main.js",
    "db:migrate": "prisma migrate deploy"
  }
}

Le Piège de l'Écoute : 0.0.0.0 vs 127.0.0.1

En local, nous écrivons souvent app.listen(3000) qui se lie par défaut à 127.0.0.1 (localhost).

Sur un hébergeur comme Render, Railway ou dans un conteneur Docker, le reverse proxy externe envoie le trafic sur l'interface réseau publique du conteneur. Si votre serveur écoute uniquement sur localhost, le routeur ne pourra jamais vous joindre, provoquant une erreur 502 Bad Gateway ou un timeout de healthcheck !

// ❌ Erreur fréquente :
app.listen(3000); // Bloqué dans le conteneur

// ✅ Bon réflexe universel de production :
const PORT = process.env.PORT || 3000;
app.listen(PORT, '0.0.0.0', () => {
  console.log(`Serveur prêt sur port ${PORT}`);
});
🌐
process.env.PORT

Ne forcez jamais un port fixe comme 8080 ou 3000. L'hébergeur cloud assigne dynamiquement un port aléatoire (ex: 10452) et transmet sa valeur via la variable PORT.

Gestion du Graceful Shutdown (SIGTERM)

Lors d'un nouveau déploiement, l'hébergeur envoie un signal SIGTERM à l'ancien conteneur pour lui demander de s'arrêter avant de lancer le nouveau. Si vous n'interceptez pas ce signal, l'application est tuée brutalement, interrompant les requêtes de vos clients en cours de paiement :

// server.ts - Interception propre des signaux d'arrêt
const server = app.listen(PORT, '0.0.0.0', () => {
  console.log(`Serveur démarré sur le port ${PORT}`);
});

const handleShutdown = async (signal: string) => {
  console.log(`Signal ${signal} reçu : fermeture ordonnée...`);
  
  // 1. Arrêter d'accepter de nouvelles connexions HTTP
  server.close(async () => {
    console.log('Serveur HTTP fermé.');
    
    // 2. Clôturer proprement les connexions à la base de données
    await prisma.$disconnect();
    console.log('Connexions Base de Données fermées.');
    
    process.exit(0);
  });

  // 3. Forcer l'arrêt après 10s si des requêtes bloquent
  setTimeout(() => {
    console.error('Arrêt forcé après délai dépassé (timeout 10s).');
    process.exit(1);
  }, 10000);
};

process.on('SIGTERM', () => handleShutdown('SIGTERM'));
process.on('SIGINT', () => handleShutdown('SIGINT'));