Bun 1.2 : Le Runtime JavaScript Qui Bat des Records de Performance
Salut HaWkers, si vous suivez l'écosystème JavaScript, vous avez probablement entendu parler de Bun. Ce runtime relativement nouveau conquiert les développeurs avec des chiffres de performance impressionnants.
Vous vous êtes déjà frustré en attendant que npm install se termine ? Ou peut-être avez-vous senti que votre serveur Node.js pourrait être plus rapide ? Bun promet de résoudre ces problèmes et bien plus encore.
Qu'est-ce que Bun
Bun est un runtime JavaScript et toolkit tout-en-un qui inclut :
Composants Principaux :
- Runtime JavaScript (alternative à Node.js)
- Package manager (alternative à npm/yarn/pnpm)
- Bundler (alternative à webpack/esbuild)
- Test runner (alternative à Jest/Vitest)
- Transpileur TypeScript natif
Le différenciateur ? Tout cela a été écrit en Zig et C++ pour une performance maximale, utilisant JavaScriptCore (moteur de Safari) au lieu de V8.
Nouveautés de Bun 1.2
Windows Natif
Enfin, un support complet pour Windows :
# Installation sur Windows (PowerShell)
powershell -c "irm bun.sh/install.ps1 | iex"
# Ou via npm
npm install -g bun
# Vérifier l'installation
bun --version
# 1.2.0Avant la version 1.2, Bun sur Windows dépendait de WSL. Maintenant il fonctionne nativement.
S3 Object Storage Natif
Bun 1.2 a introduit des APIs natives pour Amazon S3 :
// Accès natif à S3 - sans SDKs lourds
import { S3Client } from "bun";
const s3 = new S3Client({
accessKeyId: Bun.env.AWS_ACCESS_KEY_ID,
secretAccessKey: Bun.env.AWS_SECRET_ACCESS_KEY,
region: "us-east-1"
});
// Upload de fichier
const file = Bun.file("./image.png");
await s3.write("my-bucket/image.png", file);
// Download
const downloaded = await s3.file("my-bucket/image.png");
await Bun.write("./downloaded.png", downloaded);
// Streaming de gros fichiers
const stream = s3.file("my-bucket/large-video.mp4").stream();Postgres Natif
Driver PostgreSQL intégré au runtime :
// Sans installer pg ou postgres.js
import { SQL } from "bun";
const sql = new SQL({
hostname: "localhost",
database: "myapp",
username: "user",
password: "password"
});
// Queries avec tagged templates
const users = await sql`SELECT * FROM users WHERE active = true`;
// Queries paramétrées (sécurisées contre SQL injection)
const userId = 123;
const user = await sql`SELECT * FROM users WHERE id = ${userId}`;
// Transactions
await sql.begin(async (tx) => {
await tx`UPDATE accounts SET balance = balance - 100 WHERE id = 1`;
await tx`UPDATE accounts SET balance = balance + 100 WHERE id = 2`;
});
Performance Comparée
Package Manager
Comparons l'installation de dépendances :
# Projet avec ~50 dépendances
# npm
time npm install
# real: 45.2s
# yarn
time yarn install
# real: 32.1s
# pnpm
time pnpm install
# real: 18.7s
# bun
time bun install
# real: 2.3sBun est systématiquement 10-20x plus rapide que npm.
Performance Runtime
Serveur HTTP :
// Bun native server
Bun.serve({
port: 3000,
fetch(req) {
return new Response("Hello World");
}
});
// Résultats : ~185,000 req/sComparatif de requêtes par seconde :
| Runtime | Hello World | JSON API | File Serve |
|---|---|---|---|
| Bun 1.2 | 185,000 | 142,000 | 78,000 |
| Deno 2.0 | 125,000 | 95,000 | 45,000 |
| Node 22 | 118,000 | 88,000 | 52,000 |
Bundler
# Build d'un gros projet React (~500 composants)
# webpack
time npx webpack build
# real: 28.4s
# esbuild
time npx esbuild src/index.tsx --bundle --outdir=dist
# real: 0.8s
# bun
time bun build src/index.tsx --outdir=dist
# real: 0.4s
Utiliser Bun en Pratique
Créer un Projet
# Créer un projet
mkdir mon-projet && cd mon-projet
bun init
# Structure créée :
# mon-projet/
# .gitignore
# bun.lockb
# index.ts
# package.json
# README.md
# tsconfig.jsonServeur Web Complet
// server.ts
import { Hono } from "hono";
import { cors } from "hono/cors";
import { logger } from "hono/logger";
const app = new Hono();
// Middlewares
app.use("*", logger());
app.use("/api/*", cors());
// Connexion database (native Bun)
const db = new SQL({
hostname: Bun.env.DB_HOST,
database: Bun.env.DB_NAME,
username: Bun.env.DB_USER,
password: Bun.env.DB_PASSWORD
});
// Routes
app.get("/", (c) => c.text("Hello Bun!"));
app.get("/api/users", async (c) => {
const users = await db`SELECT id, name, email FROM users`;
return c.json(users);
});
app.post("/api/users", async (c) => {
const body = await c.req.json();
const { name, email } = body;
const [user] = await db`
INSERT INTO users (name, email)
VALUES (${name}, ${email})
RETURNING *
`;
return c.json(user, 201);
});
// File uploads (avec S3 natif)
app.post("/api/upload", async (c) => {
const form = await c.req.formData();
const file = form.get("file") as File;
const s3 = new S3Client({
accessKeyId: Bun.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: Bun.env.AWS_SECRET_ACCESS_KEY!,
region: "us-east-1"
});
const key = `uploads/${Date.now()}-${file.name}`;
await s3.write(`my-bucket/${key}`, file);
return c.json({ url: `https://my-bucket.s3.amazonaws.com/${key}` });
});
export default {
port: 3000,
fetch: app.fetch
};Exécuter et Développer
# Exécuter en développement (avec hot reload)
bun --watch run server.ts
# Exécuter en production
bun run server.ts
# Scripts du package.json
bun run dev
bun run build
bun run test
Système de Tests
Bun a un test runner intégré compatible avec Jest :
// math.ts
export function add(a: number, b: number): number {
return a + b;
}
export function multiply(a: number, b: number): number {
return a * b;
}
export async function fetchUser(id: number) {
const response = await fetch(`https://api.example.com/users/${id}`);
return response.json();
}// math.test.ts
import { describe, test, expect, mock, beforeEach } from "bun:test";
import { add, multiply, fetchUser } from "./math";
describe("Math functions", () => {
test("add should sum two numbers", () => {
expect(add(2, 3)).toBe(5);
expect(add(-1, 1)).toBe(0);
});
test("multiply should multiply two numbers", () => {
expect(multiply(3, 4)).toBe(12);
expect(multiply(0, 100)).toBe(0);
});
});
describe("API functions", () => {
beforeEach(() => {
// Mock du fetch global
global.fetch = mock(async (url: string) => {
return new Response(JSON.stringify({
id: 1,
name: "Test User"
}));
});
});
test("fetchUser should return user data", async () => {
const user = await fetchUser(1);
expect(user.name).toBe("Test User");
});
});# Exécuter les tests
bun test
# Avec coverage
bun test --coverage
# Watch mode
bun test --watch
# Filtrer les tests
bun test --filter "Math"
Bundler Intégré
// bun.config.ts (optionnel)
export default {
entrypoints: ["./src/index.tsx"],
outdir: "./dist",
target: "browser",
minify: true,
sourcemap: "external",
splitting: true,
plugins: [
// Plugins personnalisés
]
};# Build simple
bun build ./src/index.tsx --outdir ./dist
# Build avec minification
bun build ./src/index.tsx --outdir ./dist --minify
# Build pour Node.js
bun build ./src/server.ts --outdir ./dist --target node
# Watch mode
bun build ./src/index.tsx --outdir ./dist --watchMacros en Temps de Build
Une feature unique de Bun sont les macros qui s'exécutent au moment de la compilation :
// config.ts
export const VERSION = await Bun.file("./version.txt").text();
export const BUILD_TIME = new Date().toISOString();
// Ceci est évalué au moment du build, pas au runtime !
export const ENV_CONFIG = {
apiUrl: Bun.env.API_URL,
debug: Bun.env.DEBUG === "true"
};// app.ts
import { VERSION, BUILD_TIME } from "./config" with { type: "macro" };
console.log(`Version: ${VERSION}`);
console.log(`Built at: ${BUILD_TIME}`);
// Dans le bundle final, ces valeurs sont substituées par des strings littérales
Compatibilité avec Node.js
Bun est hautement compatible avec Node.js :
// La plupart du code Node.js fonctionne sans changements
import express from "express";
import { PrismaClient } from "@prisma/client";
import bcrypt from "bcrypt";
const app = express();
const prisma = new PrismaClient();
app.use(express.json());
app.post("/login", async (req, res) => {
const { email, password } = req.body;
const user = await prisma.user.findUnique({
where: { email }
});
if (!user) {
return res.status(401).json({ error: "User not found" });
}
const valid = await bcrypt.compare(password, user.password);
if (!valid) {
return res.status(401).json({ error: "Invalid password" });
}
res.json({ user: { id: user.id, email: user.email } });
});
// Fonctionne avec bun run ou node
app.listen(3000);APIs Node.js Supportées
// La plupart des APIs Node.js fonctionnent
import fs from "fs";
import path from "path";
import crypto from "crypto";
import { Buffer } from "buffer";
import { EventEmitter } from "events";
import { Readable, Writable } from "stream";
// process global
console.log(process.env.NODE_ENV);
console.log(process.cwd());
// APIs Bun additionnelles
const file = Bun.file("./data.json");
const content = await file.text();
const hash = Bun.hash("sha256", "data");
Quand Utiliser Bun
Cas Idéaux
1. Nouveaux Projets Nécessitant de la Performance :
// APIs haute performance
// Traitement de données en temps réel
// Serveurs WebSocket
// Microservices
Bun.serve({
port: 3000,
websocket: {
message(ws, message) {
// Broadcast à tous les clients
server.publish("chat", message);
}
},
fetch(req, server) {
if (server.upgrade(req)) {
return; // Upgrade vers WebSocket
}
return new Response("Hello!");
}
});2. Scripts et Outils CLI :
#!/usr/bin/env bun
// Script de migration de données
import { SQL } from "bun";
const sourceDb = new SQL({ /* config source */ });
const targetDb = new SQL({ /* config destination */ });
console.log("Starting migration...");
const users = await sourceDb`SELECT * FROM users`;
for (const user of users) {
await targetDb`
INSERT INTO users (id, name, email)
VALUES (${user.id}, ${user.name}, ${user.email})
`;
console.log(`Migrated user ${user.id}`);
}
console.log(`Migration complete! ${users.length} users migrated.`);3. Quand le Temps de Build Compte :
# CI/CD plus rapide
# bun install + bun build en secondes
# vs npm install + webpack en minutesQuand Éviter (Pour l'Instant)
- Projets dépendant de native addons complexes
- Écosystèmes très spécifiques à Node.js
- Quand la stabilité est plus importante que la performance
- Équipes qui ne peuvent pas absorber la courbe d'apprentissage
Migrer de Node.js
Étape 1 : Installer Bun
# Unix/Mac
curl -fsSL https://bun.sh/install | bash
# Windows
powershell -c "irm bun.sh/install.ps1 | iex"Étape 2 : Convertir package.json
# Supprimer node_modules et lockfiles anciens
rm -rf node_modules package-lock.json yarn.lock pnpm-lock.yaml
# Installer avec Bun
bun install
# Crée bun.lockbÉtape 3 : Tester la Compatibilité
# Exécuter les tests
bun test
# Exécuter l'application
bun run dev
# Vérifier que tout fonctionneÉtape 4 : Optimiser pour Bun
// Remplacer les packages par des APIs natives quand possible
// Avant : pg ou postgres.js
import { Client } from "pg";
// Après : SQL natif de Bun
import { SQL } from "bun";
// Avant : aws-sdk pour S3
import AWS from "aws-sdk";
// Après : S3 natif de Bun
import { S3Client } from "bun";
Conclusion
Bun 1.2 représente une avancée significative dans l'écosystème JavaScript. Avec une performance impressionnante, des APIs natives pour les tâches courantes, et une excellente compatibilité avec Node.js, il devient une option de plus en plus viable pour les projets sérieux.
La principale recommandation est : expérimentez. Commencez par un nouveau projet ou un script, et étendez à mesure que vous gagnez en confiance. L'écosystème Bun mûrit encore, mais la direction est prometteuse.
Si vous voulez comparer Bun avec d'autres options de runtime, je recommande de jeter un œil à un autre article : Deno 2.0 vs Node.js : La Bataille des Runtimes où vous découvrirez comment chaque runtime se positionne sur le marché actuel.

