Contactez-nous

Déploiement sur des serveurs traditionnels (Node.js/Express servant le build)

Apprenez à déployer vos applications React (SPA ou SSR) en les servant depuis un serveur Node.js traditionnel, souvent en utilisant le framework Express.

Quand l'hébergement statique ne suffit plus : Le serveur applicatif

Si les plateformes d'hébergement statique sont idéales pour les SPA et les sites SSG, elles atteignent leurs limites lorsque votre application React nécessite une logique côté serveur plus complexe au moment de la requête. C'est notamment le cas pour :

  • Les applications nécessitant un Rendu Côté Serveur (Server-Side Rendering - SSR) dynamique pour chaque requête (par exemple, avec Next.js ou Remix en mode SSR, ou une implémentation SSR manuelle).
  • Les applications qui intègrent une API backend substantielle qu'on ne souhaite pas ou ne peut pas implémenter uniquement avec des fonctions serverless limitées.
  • Les cas où l'on a besoin d'un contrôle plus fin sur l'environnement serveur, les dépendances système, ou l'infrastructure réseau.
  • L'intégration dans une infrastructure existante basée sur des serveurs Node.js.

Dans ces scénarios, une approche courante consiste à déployer l'application React sur un serveur Node.js traditionnel, souvent en utilisant un micro-framework comme Express.js pour gérer les requêtes HTTP et servir les fichiers ou exécuter la logique SSR.

Scénario 1 : Servir une SPA (Build Statique) depuis Express

Même si votre application est une SPA (build statique généré par Vite, CRA, etc.), vous pourriez vouloir la servir depuis votre propre serveur Node.js/Express, par exemple si ce serveur gère également l'API backend de l'application ou si vous avez des besoins de routage ou de middleware spécifiques côté serveur.

Le processus implique :

  1. Construire l'application React : Exécutez npm run build pour générer le dossier de build statique (ex: `build` ou `dist`).
  2. Créer un serveur Express : Mettez en place un serveur Express simple.
  3. Servir les fichiers statiques : Configurez Express pour servir le contenu du dossier de build. Le middleware `express.static` est utilisé pour cela.
  4. Gérer le routage SPA : Comme pour l'hébergement statique, vous devez configurer le serveur pour renvoyer le fichier `index.html` principal pour toutes les routes non-API qui ne correspondent pas à un fichier statique existant. Cela permet au routeur côté client de React de prendre le relais.

Exemple de serveur Express simple :

const express = require('express');
const path = require('path');
const app = express();
const port = process.env.PORT || 3000;

// Chemin vers le dossier de build de l'application React
const buildPath = path.join(__dirname, 'client', 'build'); // Adapter si nécessaire

// 1. Servir les fichiers statiques (JS, CSS, images...) depuis le dossier de build
app.use(express.static(buildPath));

// 2. Servir l'API (si applicable)
app.get('/api/hello', (req, res) => {
  res.json({ message: 'Bonjour depuis l\'API' });
});

// 3. Pour toutes les autres requêtes GET (non-API, non-fichier statique),
// renvoyer l'index.html principal pour que React Router gère la route.
app.get('*', (req, res) => {
  res.sendFile(path.join(buildPath, 'index.html'));
});

app.listen(port, () => {
  console.log(`Serveur écoutant sur le port ${port}`);
});

Pour le déploiement, vous copiez le dossier de build et ce fichier serveur sur votre machine hôte (VM, serveur dédié), installez les dépendances serveur (`npm install express`), et lancez le serveur Node.js (souvent avec un gestionnaire de processus comme PM2 pour la robustesse).

Scénario 2 : Déployer une application SSR (Next.js, Remix, etc.)

Lorsque vous utilisez un meta-framework comme Next.js ou Remix en mode SSR, le processus de build (`next build`, `remix build`) génère non seulement des assets statiques, mais aussi un serveur Node.js optimisé capable d'exécuter la logique SSR et les API Routes/Actions.

Le déploiement consiste alors à :

  1. Construire l'application : Exécutez la commande de build spécifique au framework (ex: `npm run build`). Cela crée un dossier de sortie (ex: `.next`, `build`) contenant le serveur optimisé et les assets.
  2. Copier le build : Transférez le contenu du dossier de build et les dépendances de production (`node_modules`, `package.json`) sur le serveur cible.
  3. Lancer le serveur du framework : Utilisez la commande fournie par le framework pour démarrer le serveur de production (ex: npm start qui exécute souvent next start ou une commande similaire pour Remix).

Le serveur intégré du framework gère alors automatiquement le service des assets statiques, l'exécution du SSR pour les pages concernées, et le routage vers les API Routes / Actions.

Il est également possible d'utiliser un serveur personnalisé (comme Express) pour lancer une application Next.js/Remix SSR, bien que cela soit moins courant et souvent plus complexe que d'utiliser le serveur intégré. Cela peut être nécessaire pour une intégration poussée avec une infrastructure Express existante ou pour des besoins de middleware très spécifiques.

Considérations pour le déploiement sur serveur traditionnel

  • Gestion du serveur : Contrairement aux plateformes statiques, vous êtes responsable de la gestion du serveur (mises à jour système, sécurité, configuration réseau).
  • Gestion des processus : Il est fortement recommandé d'utiliser un gestionnaire de processus Node.js comme PM2 ou systemd pour :
    • Maintenir le serveur Node.js en cours d'exécution même s'il plante.
    • Gérer les redémarrages automatiques lors des mises à jour.
    • Faciliter la gestion des logs.
    • Permettre le clustering pour utiliser tous les coeurs du CPU.
  • Configuration du serveur web inverse (Reverse Proxy) : Il est courant de placer un serveur web comme Nginx ou Apache devant votre serveur Node.js. Ce serveur inverse peut gérer le trafic entrant, la terminaison SSL (HTTPS), la compression Gzip, la mise en cache de certains assets, le load balancing, et rediriger les requêtes vers l'application Node.js appropriée.
  • Variables d'environnement serveur : Les clés API secrètes et autres configurations sensibles doivent être définies comme des variables d'environnement sur le serveur lui-même, en dehors du code source ou des fichiers `.env` versionnés.
  • Build sur le serveur vs CI/CD : Vous pouvez soit exécuter `npm run build` directement sur le serveur de production (moins recommandé), soit, idéalement, effectuer le build dans un environnement d'intégration continue (CI) et ne déployer que les artefacts de build finaux et les dépendances de production sur le serveur.

Avantages et inconvénients

Avantages :

  • Contrôle total : Contrôle complet sur l'environnement serveur, les dépendances et la configuration.
  • Flexibilité : Permet le SSR dynamique, l'intégration d'API complexes, et des configurations personnalisées.
  • Potentiellement moins cher (à petite échelle) : Si vous gérez déjà des serveurs, l'ajout d'une application Node.js peut être économique.

Inconvénients :

  • Complexité accrue : Nécessite des compétences en administration système et en gestion de serveurs Node.js.
  • Maintenance : Responsabilité de la maintenance du serveur, des mises à jour, de la sécurité.
  • Scalabilité manuelle : La mise à l'échelle (ajout de serveurs, load balancing) doit être gérée manuellement ou via des outils d'orchestration.
  • Moins d'automatisation "out-of-the-box" : Comparé aux plateformes PaaS/statiques modernes.

Conclusion : Pour le contrôle et le SSR/Backend intégré

Déployer une application React sur un serveur Node.js/Express traditionnel est une stratégie viable et nécessaire lorsque vous avez besoin de capacités de rendu côté serveur dynamiques, d'une intégration backend plus poussée, ou d'un contrôle fin sur l'environnement d'hébergement.

Que ce soit pour servir un simple build de SPA ou pour exécuter une application SSR/full-stack construite avec un meta-framework, cette approche offre une grande flexibilité mais demande en contrepartie une gestion plus active de l'infrastructure serveur et du processus de déploiement.