| name | bun |
| description | Build fast applications with Bun JavaScript runtime. Use when creating Bun projects, using Bun APIs, bundling, testing, or optimizing Node.js alternatives. Triggers on Bun, Bun runtime, bun.sh, bunx, Bun serve, Bun test, JavaScript runtime. |
Bun - The Fast JavaScript Runtime
Build and run JavaScript/TypeScript applications with Bun's all-in-one toolkit.
Quick Start
curl -fsSL https://bun.sh/install | bash
powershell -c "irm bun.sh/install.ps1 | iex"
bun init
bun run index.ts
bun install
bun run dev
Package Management
bun install
bun add express
bun add -d typescript
bun add -g serve
bun remove express
bun update
bunx prisma generate
bunx create-next-app
bun install --frozen-lockfile
bun.lockb vs package-lock.json
bun install --yarn
bun install
Bun Runtime
Run Files
bun run index.ts
bun run index.js
bun run index.jsx
bun --watch run index.ts
bun --hot run server.ts
Built-in APIs
const file = Bun.file('data.json');
const content = await file.text();
const json = await file.json();
const bytes = await file.arrayBuffer();
await Bun.write('output.txt', 'Hello, Bun!');
await Bun.write('data.json', JSON.stringify({ key: 'value' }));
await Bun.write('image.png', await fetch('https://example.com/img.png'));
const file = Bun.file('data.json');
console.log(file.size);
console.log(file.type);
console.log(file.lastModified);
const glob = new Bun.Glob('**/*.ts');
for await (const file of glob.scan('.')) {
console.log(file);
}
HTTP Server
const server = Bun.serve({
port: 3000,
fetch(req) {
const url = new URL(req.url);
if (url.pathname === '/') {
return new Response('Hello, Bun!');
}
if (url.pathname === '/json') {
return Response.json({ message: 'Hello!' });
}
return new Response('Not Found', { status: 404 });
},
});
console.log(`Server running at http://localhost:${server.port}`);
Advanced Server
Bun.serve({
port: 3000,
async fetch(req, server) {
const url = new URL(req.url);
if (url.pathname === '/ws') {
const upgraded = server.upgrade(req, {
data: { userId: '123' },
});
if (upgraded) return undefined;
}
if (url.pathname.startsWith('/static/')) {
const filePath = `./public${url.pathname}`;
const file = Bun.file(filePath);
if (await file.exists()) {
return new Response(file);
}
}
if (url.pathname === '/api/data' && req.method === 'POST') {
const body = await req.json();
return Response.json({ received: body });
}
return new Response('Not Found', { status: 404 });
},
websocket: {
open(ws) {
console.log('Client connected:', ws.data.userId);
ws.subscribe('chat');
},
message(ws, message) {
ws.publish('chat', message);
},
close(ws) {
console.log('Client disconnected');
},
},
error(error) {
return new Response(`Error: ${error.message}`, { status: 500 });
},
});
WebSocket Client
const ws = new WebSocket('ws://localhost:3000/ws');
ws.onopen = () => {
ws.send('Hello, server!');
};
ws.onmessage = (event) => {
console.log('Received:', event.data);
};
Bun APIs
SQLite (Built-in)
import { Database } from 'bun:sqlite';
const db = new Database('mydb.sqlite');
db.run(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE
)
`);
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
insert.run('Alice', 'alice@example.com');
const query = db.prepare('SELECT * FROM users WHERE id = ?');
const user = query.get(1);
const allUsers = db.prepare('SELECT * FROM users').all();
const insertMany = db.transaction((users) => {
for (const user of users) {
insert.run(user.name, user.email);
}
});
insertMany([
{ name: 'Bob', email: 'bob@example.com' },
{ name: 'Charlie', email: 'charlie@example.com' },
]);
Password Hashing (Built-in)
const hash = await Bun.password.hash('mypassword', {
algorithm: 'argon2id',
memoryCost: 65536,
timeCost: 2,
});
const isValid = await Bun.password.verify('mypassword', hash);
Spawn Processes
const proc = Bun.spawn(['ls', '-la'], {
cwd: '/home/user',
env: { ...process.env, MY_VAR: 'value' },
stdout: 'pipe',
});
const output = await new Response(proc.stdout).text();
console.log(output);
const result = Bun.spawnSync(['echo', 'hello']);
console.log(result.stdout.toString());
const { stdout } = Bun.spawn({
cmd: ['sh', '-c', 'echo $HOME'],
stdout: 'pipe',
});
Hashing & Crypto
const hash = Bun.hash('hello world');
const sha256 = new Bun.CryptoHasher('sha256');
sha256.update('data');
const digest = sha256.digest('hex');
const md5 = Bun.CryptoHasher.hash('md5', 'data', 'hex');
const hmac = Bun.CryptoHasher.hmac('sha256', 'secret-key', 'data', 'hex');
Bundler
bun build ./src/index.ts --outdir ./dist
bun build ./src/index.ts \
--outdir ./dist \
--minify \
--sourcemap \
--target browser \
--splitting \
--entry-naming '[dir]/[name]-[hash].[ext]'
Build API
const result = await Bun.build({
entrypoints: ['./src/index.ts'],
outdir: './dist',
minify: true,
sourcemap: 'external',
target: 'browser',
splitting: true,
naming: {
entry: '[dir]/[name]-[hash].[ext]',
chunk: '[name]-[hash].[ext]',
asset: '[name]-[hash].[ext]',
},
external: ['react', 'react-dom'],
define: {
'process.env.NODE_ENV': JSON.stringify('production'),
},
loader: {
'.png': 'file',
'.svg': 'text',
},
});
if (!result.success) {
console.error('Build failed:', result.logs);
}
Testing
import { describe, test, expect, beforeAll, afterAll, mock } from 'bun:test';
describe('Math operations', () => {
test('addition', () => {
expect(1 + 1).toBe(2);
});
test('array contains', () => {
expect([1, 2, 3]).toContain(2);
});
test('object matching', () => {
expect({ name: 'Alice', age: 30 }).toMatchObject({ name: 'Alice' });
});
test('async test', async () => {
const result = await Promise.resolve(42);
expect(result).toBe(42);
});
test('throws error', () => {
expect(() => {
throw new Error('fail');
}).toThrow('fail');
});
});
const mockFn = mock(() => 'mocked');
mockFn();
expect(mockFn).toHaveBeenCalled();
mock.module('./database', () => ({
query: mock(() => [{ id: 1 }]),
}));
bun test
bun test --watch
bun test user.test.ts
bun test --coverage
Node.js Compatibility
import fs from 'fs';
import path from 'path';
import { createServer } from 'http';
import express from 'express';
const data = fs.readFileSync('file.txt', 'utf-8');
const fullPath = path.join(__dirname, 'file.txt');
const app = express();
app.get('/', (req, res) => res.send('Hello!'));
app.listen(3000);
Node.js vs Bun APIs
import { readFile } from 'fs/promises';
const content = await readFile('file.txt', 'utf-8');
const content = await Bun.file('file.txt').text();
import crypto from 'crypto';
const hash = crypto.createHash('sha256').update('data').digest('hex');
const hash = Bun.CryptoHasher.hash('sha256', 'data', 'hex');
Environment Variables
const dbUrl = Bun.env.DATABASE_URL;
const apiKey = process.env.API_KEY;
HTTP Client
const response = await fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token',
},
body: JSON.stringify({ key: 'value' }),
});
const data = await response.json();
const response = await fetch('https://api.example.com/stream');
const reader = response.body?.getReader();
while (true) {
const { done, value } = await reader!.read();
if (done) break;
console.log(new TextDecoder().decode(value));
}
Project Structure
my-bun-project/
โโโ src/
โ โโโ index.ts # Entry point
โ โโโ routes/
โ โ โโโ api.ts
โ โโโ lib/
โ โโโ database.ts
โโโ tests/
โ โโโ index.test.ts
โโโ public/
โ โโโ static files
โโโ package.json
โโโ bunfig.toml # Bun config (optional)
โโโ tsconfig.json
โโโ .env
bunfig.toml
[install]
exact = true
registry = "https://registry.npmjs.org"
[run]
preload = ["./instrumentation.ts"]
[test]
coverage = true
coverageDir = "coverage"
[bundle]
minify = true
sourcemap = "external"
Performance Comparison
| Operation | Node.js | Bun | Speedup |
|---|
| Start time | ~40ms | ~7ms | 5.7x |
| Package install | ~10s | ~1s | 10x |
| File read | baseline | faster | 10x |
| HTTP server | baseline | faster | 4x |
| SQLite | external | built-in | 3x |
| TypeScript | compile needed | native | โ |
Resources