Bun, Deno ou Node.js : quel runtime JavaScript choisir ?
Compatibilité npm, TypeScript, performances, outils intégrés et maturité en production : ce qui distingue vraiment les trois runtimes, et lequel adopter.
Pendant plus de dix ans, la question ne se posait pas. Pour exécuter du JavaScript hors du navigateur, il y avait Node.js. Puis le créateur de Node.js lui-même a lancé Deno pour corriger ce qu'il considérait comme ses erreurs de conception, et Bun est arrivé avec une promesse simple : faire la même chose que Node, en beaucoup plus rapide.
Un runtime JavaScript est le programme qui exécute du code JavaScript en dehors d'un navigateur. Il fournit un moteur (qui transforme le code en instructions machine) et des API pour ce que le navigateur ne fait pas : lire des fichiers, ouvrir un port réseau, lancer des processus.
Les trois coexistent aujourd'hui, et ils se ressemblent de plus en plus. Les différences qui restent sont pourtant décisives selon le projet.
Trois philosophies
| Node.js | Deno | Bun | |
|---|---|---|---|
| Sortie | 2009 | 2020 (Deno 2 en 2024) | 2023 (version 1.0) |
| Moteur JavaScript | V8 (Chrome) | V8 (Chrome) | JavaScriptCore (Safari) |
| Écrit en | C++ | Rust | Zig |
| Idée directrice | Stabilité, écosystème | Sécurité, standards du web | Vitesse, tout-en-un |
| TypeScript | Suppression des types native (sans vérification) | Natif | Natif |
| Gestionnaire de paquets | npm (séparé) | Intégré | Intégré, très rapide |
| Tests, bundler, formateur | Outils séparés (test runner intégré) | Tout intégré | Tests et bundler intégrés |
| Permissions | Accès total par défaut | Tout interdit par défaut | Accès total par défaut |
| Compatibilité npm | Totale, par définition | Très bonne depuis Deno 2 | Très bonne, quelques cas limites |
Le même serveur HTTP dans les trois
import http from 'node:http'
http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ runtime: 'node' }))
}).listen(3000)Deno.serve({ port: 3000 }, () => Response.json({ runtime: 'deno' }))Bun.serve({
port: 3000,
fetch: () => Response.json({ runtime: 'bun' }),
})node node-server.mjs
deno run --allow-net deno-server.ts
bun bun-server.tsDeno et Bun utilisent les API standard du web (Request, Response, fetch), les mêmes que dans le navigateur ou dans les fonctions edge. Node.js garde son API historique http, mais supporte aussi fetch et les objets Response depuis plusieurs versions. Et surtout : le code Node.js tourne tel quel sous Bun et, dans la grande majorité des cas, sous Deno.
Node.js : le choix par défaut, pour de bonnes raisons
Node.js n'a plus grand-chose à prouver. Des millions d'applications en production, chaque bibliothèque npm testée d'abord sur lui, chaque hébergeur et chaque outil de monitoring qui le supportent nativement.
Il a aussi rattrapé une partie de son retard :
- TypeScript : les versions récentes exécutent directement des fichiers
.tsen supprimant les annotations de type. Elles ne vérifient pas les types, c'est toujours le rôle detsc, mais plus besoin d'étape de compilation pour lancer un script. - Outils intégrés :
node --testpour les tests,node --watchpour le rechargement,--env-filepour charger un fichier.env. - Versions LTS : chaque version paire bénéficie de trente mois de support. Pour une entreprise, c'est une garantie que ni Bun ni Deno n'offrent au même niveau.
Pour la mise en production classique sur un serveur, héberger une application Node.js sur un VPS reste le chemin le plus documenté qui existe, avec un gestionnaire de processus comme PM2, présenté dans sa formation dédiée.
Ses faiblesses : un démarrage plus lent, une installation des dépendances plus lente avec npm, et un outillage dispersé (bundler, linter, formateur à choisir et configurer soi-même).
Bun : la vitesse et le confort
Bun a été conçu pour remplacer non seulement Node.js, mais aussi npm, Jest, esbuild et nodemon. Un seul binaire fait tout :
bun install # installe les dépendances de package.json
bun run dev # lance un script de package.json
bun test # lance les tests, syntaxe compatible Jest
bun build ./src/index.ts --outdir ./dist # bundle le code
bun --watch index.ts # recharge à chaque modificationCe qui frappe à l'usage, c'est la vitesse : bun install est souvent plusieurs fois plus rapide que npm install, et le démarrage d'un script est quasi instantané. Sur un projet avec beaucoup de dépendances et de tests, le gain se ressent à chaque commande.
Bun lit directement TypeScript et JSX, charge les fichiers .env tout seul, et embarque des API natives pratiques : SQLite intégré, client Postgres, lecture de fichiers optimisée.
Ses faiblesses : la compatibilité avec Node.js est très élevée mais pas totale. Les modules natifs compilés en C++ pour Node et certaines API rarement utilisées peuvent poser problème. Et le projet bouge vite, ce qui veut dire des changements fréquents et moins de recul sur la stabilité à long terme.
En revanche, Bun en tant que gestionnaire de paquets et lanceur de tests sur un projet Node.js est un choix quasi sans risque. Beaucoup d'équipes l'adoptent ainsi, sans changer de runtime en production.
Deno : la sécurité et les standards
Deno part d'un constat : un script Node.js peut, par défaut, lire tous vos fichiers, ouvrir des connexions réseau et lire vos variables d'environnement. Une dépendance npm compromise a les mêmes droits que votre code.
Deno inverse la logique : tout est interdit par défaut.
deno run script.ts # aucun accès
deno run --allow-net=api.exemple.fr script.ts # réseau vers un seul domaine
deno run --allow-read=./data --allow-env script.tsUn script qui tente d'accéder à ce qui n'est pas autorisé échoue avec un message explicite. Pour exécuter du code tiers ou des scripts d'automatisation, c'est une vraie garantie.
Depuis Deno 2, la compatibilité avec npm et package.json est bonne : on importe un paquet npm avec le préfixe npm:, ou on travaille dans un projet Node existant. Deno intègre aussi formateur, linter, tests, bundler et documentation, sans aucune configuration.
Ses faiblesses : l'écosystème et la communauté sont plus petits, les permissions demandent un peu de rigueur au début, et la majorité des tutoriels en ligne restent écrits pour Node.js.
Et les performances ?
Les benchmarks publiés par chaque projet montrent tous leur runtime en tête. Sur des micro-tests (servir « Hello world », démarrer un script), Bun est généralement le plus rapide. Mais dans une vraie application, le temps passé à attendre la base de données, une API externe ou le disque écrase ces écarts.
Ce qui change réellement le quotidien, ce sont les temps d'installation, de démarrage et d'exécution des tests. Là, Bun a un avantage net et mesurable sur tout projet de taille moyenne.
Docker et déploiement
Les trois disposent d'images Docker officielles (node, denoland/deno, oven/bun). Un service passe de l'un à l'autre en changeant l'image et la commande de démarrage dans son fichier Docker Compose :
services:
api:
image: oven/bun:1
working_dir: /app
volumes:
- ./:/app
command: ["bun", "run", "src/index.ts"]
ports:
- "3000:3000"Côté plateformes, Node.js est supporté partout. Bun et Deno sont supportés par la plupart des hébergeurs modernes, mais vérifiez avant de choisir un hébergeur serverless ou une plateforme d'entreprise.
Lequel choisir
| Situation | Choix |
|---|---|
| Application en production pour une entreprise, équipe existante | Node.js |
| Nouveau projet perso ou side-project | Bun |
| Accélérer les installations et les tests d'un projet Node existant | Bun comme gestionnaire de paquets et test runner |
| Scripts d'automatisation, code tiers à exécuter en sécurité | Deno |
| Fonctions edge, API proches des standards du web | Deno ou Bun |
| Dépendances avec modules natifs C++ | Node.js |
| Apprendre le JavaScript côté serveur | Node.js (le plus de ressources) |
Mon avis : Node.js en production tant qu'une raison précise ne pousse pas ailleurs, et Bun sur tout ce qui est développement local, outillage et nouveaux projets personnels. Deno mérite un essai pour les scripts : sa sécurité par défaut est un vrai argument, que les deux autres n'offrent pas. Et quel que soit le runtime, TypeScript est devenu la norme : les trois l'exécutent désormais sans configuration.
Bun, Deno ou Node.js ? La bonne nouvelle, c'est que le choix est réversible. Le code écrit pour Node.js tourne presque partout, et les trois convergent vers les mêmes standards du web. Choisissez Node.js pour la sérénité, Bun pour la vitesse et le confort, Deno pour la sécurité. Puis gardez votre code proche des API standard (fetch, Request, Response) : c'est la meilleure assurance de pouvoir changer d'avis plus tard.