Il y a une confusion tenace autour de Vercel : beaucoup de développeurs Node.js croient y déployer un serveur, alors qu’ils y déploient en réalité un paquet de fonctions serverless déguisées en serveur. Cette nuance change tout. Une app Express qui tourne depuis trois ans sur un VPS à 5 € ne se comporte pas de la même manière une fois portée sur la cloud platform de Vercel, et la plupart des tutos génériques passent cette bascule sous silence.

Vercel est excellent pour les API Node.js légères et les applications orientées web, catastrophique pour les workloads stateful ou long-running. La frontière entre les deux se joue sur trois critères précis.

Qu’est-ce que Vercel, vraiment

Vercel est une cloud platform qui transforme un push git en deployment HTTPS sans gérer de serveur. Elle a gagné en adoption via Next.js, dont elle est l’éditeur, mais déploie aussi Express, Fastify, Koa ou du vanilla Node.

Le modèle technique repose sur les Vercel Functions : chaque route devient une fonction serverless exécutée à la demande. Pas de processus long-running, pas de port à gérer, pas de systemd. Cette bascule explique les avantages (scaling automatique, zéro maintenance, previews par branche) et les limites (cold starts, payload plafonné, pas d’état en mémoire entre requêtes).

Sur des besoins plus lourds, d’autres options méritent d’être pesées avant le deploy. Voir notamment le comparatif entre Next.js et Remix.

Avant de déployer : checklist des prérequis

Un deploy qui échoue est presque toujours un problème de préparation, pas de plateforme. La liste est courte mais aucune ligne n’est optionnelle.

  • Une version de Node.js supportée : Vercel suit les versions LTS, et fige la version via le champ engines du package.json ou le fichier .nvmrc
  • Un compte Vercel connecté à un provider git (GitHub, GitLab, Bitbucket)
  • Un dépôt git avec l’application poussée sur une branche
  • Un package.json à la racine avec un script build s’il y a une étape de build, et un start si vous déployez une app Express
  • Une application qui fonctionne localement via npm start ou npm run dev sans erreur

Sur le code lui-même, trois points à vérifier. Les dépendances lourdes doivent passer : le bundle total d’une function est limité en taille, et importer un SDK de 200 MB pour utiliser une seule méthode fait échouer le deploy. Les chemins de fichiers doivent être relatifs et sensibles à la casse, parce que le runtime Linux de Vercel ne pardonne pas ce que macOS laisse passer. Et les secrets doivent déjà être sortis du code, prêts à être injectés via les variables d’environnement du dashboard.

Choisir la bonne méthode de deployment

Il existe trois workflows pour déployer.

MéthodeAvantage principalLimiteQuand la choisir
Git (auto-deploy)Un push = un deploy, previews par PRNécessite un dépôt git distantProjets d’équipe, dès qu’il y a plus d’un développeur
Vercel CLIDeploy depuis le terminal, scripts customPas de previews automatiques sur PRPrototypes, scripts de déploiement ad hoc
Interface web (import)Setup initial très rapidePeu adapté au quotidienPremier deploy d’un projet existant

Le défaut pour une équipe : git. Un dépôt connecté déclenche un deployment à chaque commit sur la branche de prod, et une preview URL sur chaque PR. La revue de code s’appuie alors sur un environnement réel. La CLI sert aux hotfix sans passage par git ou à l’intégration dans un pipeline custom. L’interface web n’a qu’un usage légitime : le tout premier import d’un projet existant.

Déployer avec Vercel CLI : la méthode étape par étape

La CLI reste le moyen le plus rapide de comprendre ce qui se passe sous le capot. Le parcours tient en quatre commandes.

Installer Vercel CLI

npm i -g vercel

L’installation est globale, la version s’affiche avec vercel --version. Si npm bloque sur les permissions, privilégier un gestionnaire de versions Node comme nvm plutôt que de forcer avec sudo, qui crée des problèmes de propriété de fichiers plus tard.

Se connecter à son compte

vercel login

La commande ouvre le navigateur pour authentifier, puis écrit un token local dans ~/.local/share/com.vercel.cli. Ce token persiste entre les sessions, on ne se reconnecte que lors d’un changement de machine ou après expiration.

Lancer le premier deploy

Depuis la racine du project :

vercel

Au premier lancement, la CLI pose quelques questions : lier à quel compte, utiliser quel nom de projet, quel répertoire racine, quels overrides de build. Les réponses sont enregistrées dans .vercel/project.json pour les deploys suivants. Le résultat est une preview URL, c’est-à-dire un deployment fonctionnel mais non promu en production.

Passer en production

vercel --prod

Cette commande promeut le deployment sur le domaine de production. La distinction preview/prod est centrale sur Vercel : les previews servent à la revue, la prod sert les utilisateurs finaux. Le même binaire, le même code, deux URL différentes, une seule source de vérité. C’est un mécanisme qui a fait ses preuves ailleurs, notamment dans les workflows décrits dans le guide des Server Components React, où les previews permettent de valider des changements de rendu avant merge.

Adapter Express au modèle serverless

La plupart des tutos traitent Express comme si Vercel le faisait tourner en continu. C’est faux.

Une app Express classique expose un serveur qui écoute sur un port. Sur Vercel, il n’y a pas de port à écouter : le runtime appelle votre handler quand une requête arrive. La transformation tient en deux règles.

Première règle : exporter l’app, pas l’écouter. Dans un app.js classique, on termine par app.listen(3000). Sur Vercel, on remplace par module.exports = app (ou export default app en ESM). Le fichier doit se trouver dans un dossier api/ à la racine ou être référencé dans vercel.json.

Deuxième règle : une function par route ou une function qui route tout. L’approche la plus simple, surtout pour une migration, est de garder un unique handler Express qui gère tout le routing en interne. Le vercel.json rewrite alors toutes les requêtes vers ce handler :

{
  "rewrites": [
    { "source": "/(.*)", "destination": "/api/index" }
  ]
}

Les assets static (CSS, images, JS bundlé) sortent du circuit function : ils sont servis par le CDN directement depuis le dossier public/ ou le dossier de sortie du build. Pas besoin de express.static en production, Vercel s’en charge. Cette bascule vaut d’autant plus que les assets static impactent directement les Core Web Vitals, qui sont précisément ce qu’un CDN edge optimise sans intervention manuelle.

Sur les middlewares qui dépendent d’un état partagé (sessions en mémoire, rate limiter local, cache process), il faut basculer vers une solution externe : Redis, KV store, base de données. Entre deux requêtes, la function peut être relancée, l’état en mémoire est perdu. C’est vrai pour les sessions Express, vrai aussi pour les stores côté client comme Zustand, avec une nuance : le client persiste, le serveur non.

Cas pratique TypeScript : structure et config

Les guides Vercel couvrent rarement TypeScript avec une app Node.js custom. Structure qui tient :

mon-app/
├── api/
│   └── index.ts       # entrée unique, exporte le handler
├── src/
│   ├── routes/
│   └── services/
├── public/            # assets static
├── package.json
├── tsconfig.json
└── vercel.json

Le package.json déclare TypeScript en devDependency et expose un script build :

{
  "scripts": {
    "build": "tsc",
    "dev": "vercel dev"
  },
  "engines": { "node": "20.x" }
}

Vercel détecte TypeScript et lance le build avant le deploy. Pas besoin de compiler à la main ni de pusher les .js générés. Le api/index.ts importe l’app Express et l’exporte par défaut, le tsconfig.json cible node, pas dom. Si le build échoue, les logs apparaissent dans le terminal et le dashboard. Sur les erreurs classiques de portage, un inventaire des pièges TypeScript fréquents sauve du temps.

Ce que change le serverless, concrètement

Trois contraintes à garder en tête.

Le payload maximum est de 4,5 MB par requête et par réponse sur l’offre standard. Ce plafond suffit pour une API JSON normale, mais il fait exploser les endpoints qui servent des uploads de fichiers, génèrent des PDF volumineux, ou proxifient des téléchargements. La solution propre passe par du signed upload direct vers un stockage objet, pas par un proxy via une function.

Le cold start est le délai de démarrage d’une function qui n’a pas tourné depuis quelques minutes. Typiquement quelques centaines de millisecondes pour une app Node.js légère, parfois plus d’une seconde pour une app avec beaucoup de dépendances chargées à l’init. Ce délai s’applique à la première requête après une période d’inactivité, pas aux suivantes. Pour une API grand public à trafic régulier, c’est invisible. Pour un endpoint rarement appelé mais qui doit répondre vite, c’est un critère rédhibitoire.

Les routes se déclarent par convention de fichiers (un fichier dans api/ devient une route) ou via vercel.json. Pas de serveur qui démarre, pas de middleware global qui s’applique partout : chaque function est isolée. Les patterns Express classiques (un middleware d’auth appliqué à tout un router) doivent être réimplémentés dans un helper appelé au début de chaque handler.

Erreurs fréquentes et comment les résoudre

Les trois-quarts des échecs de deployment tombent dans une poignée de catégories identifiables.

Build qui échoue sans message clair. Neuf fois sur dix, c’est une variable d’environnement manquante à l’étape de build. Vérifier dans le dashboard que les env vars sont bien définies pour le scope Production (et aussi Preview si les PR doivent builder). Un secret disponible en local mais absent du dashboard plante systématiquement.

Routes qui retournent 404 alors que le code est correct. Le fichier n’est pas au bon endroit. Une route doit être un fichier exécutable dans api/, ou être explicitement routée via vercel.json. Un app.get('/hello') au milieu d’un fichier non-api/ ne sera jamais appelé.

Imports Express qui cassent. Les handlers doivent être compatibles avec la signature attendue par Vercel, qui accepte (req, res) similaire à Node.js standard. Si une app Express exporte une fonction qui en attend trois (middleware pattern), Vercel ne l’appellera pas comme attendu. Le fix consiste à wrapper l’app dans un handler qui transfère la requête.

Problèmes de git et de branches. La branche de production se configure dans le dashboard. Par défaut c’est main. Un push sur master sur un projet configuré en main crée des previews, pas des deployments de production. Erreur silencieuse classique qui fait perdre une heure.

Les imports relatifs qui plantent en prod mais pas en local. macOS est insensible à la casse, Linux non. import helper from './Helper' fonctionne sur votre Mac et échoue sur Vercel. On a passé une matinée entière à chercher une fuite mémoire avant de comprendre qu’un H majuscule suffisait à tout casser. Un linter correctement configuré attrape ça avant le push.

Côté outils, GitHub Copilot ou Claude Code face à Cursor attrapent ces patterns avant le push. Pas magique, mais ça évite les allers-retours sur la config.

Bonnes pratiques pour un deployment durable

Séparer prod, staging, preview avec des env vars distinctes par scope. Garder vercel.json court. Tester toute modif d’infra sur une preview avant merge. Une revue hebdo des logs évite qu’un warning ignoré au premier deploy devienne une erreur au dixième.

Côté outillage, le comparatif Vite / Turbopack influe directement sur la durée de build. Les techniques d’optimisation du crawl budget transposent au frontend servi par Vercel, et les routes API Next.js avec authentification restent le terrain de test classique de la bascule serverless.

Questions fréquentes

Vercel convient-il à toutes les applications Node.js ?

Non. Les apps qui ouvrent des connexions WebSocket persistantes, les workers qui tournent en continu, les jobs cron de plus de quelques secondes et les services qui maintiennent un état en mémoire entre requêtes sont mal adaptés au modèle serverless. Pour tout le reste (API REST, apps Next.js, services stateless, back-office léger), Vercel est un choix robuste.

Peut-on déployer Express sans rien changer au code ?

Pas vraiment. Il faut au minimum retirer le app.listen() et exporter l’app, placer le fichier dans api/ ou le router via vercel.json. Les middlewares qui dépendent d’un état en mémoire doivent être externalisés. Une app Express simple se porte en moins d’une heure ; une app avec sessions locales et cache interne demande un refactor plus sérieux.

Pourquoi mes variables d’environnement ne sont pas lues ?

Les env vars doivent être définies dans le dashboard Vercel avec le bon scope. Une variable définie uniquement en Development n’est pas disponible en Production. Après ajout, redéployer est nécessaire : les deployments existants conservent les env vars telles qu’elles étaient au moment du build.

Git, CLI ou interface web : que choisir au quotidien ?

Git pour 90 % des cas : c’est le workflow que Vercel optimise en priorité, avec les previews par PR et le rollback en un clic. La CLI pour les scripts de déploiement custom et les hotfix ponctuels. L’interface web sert uniquement au premier import d’un projet et aux réglages de configuration ; on n’y revient pas pour déployer.

Quiz personnalisé

Votre recommandation sur déployer une application node.js sur vercel

Quelques questions rapides pour adapter la recommandation à votre cas.

Q1 Votre situation sur déployer une application node.js sur vercel ?
Q2 Votre priorité ?
Q3 Votre horizon ?