Bun Node.js Compatibility
One of Bun's design goals is compatibility with the Node.js ecosystem. This chapter introduces Bun's Node.js compatibility and migration guide.
Compatibility Overview
Supported Node.js APIs
Bun supports most Node.js core modules:
| Module | Compatibility | Description |
|---|---|---|
fs | ✅ Complete | File system |
path | ✅ Complete | Path operations |
http | ✅ Most | HTTP server and client |
https | ✅ Most | HTTPS support |
crypto | ✅ Most | Cryptographic functions |
buffer | ✅ Complete | Buffer operations |
stream | ✅ Most | Stream processing |
events | ✅ Complete | Event emitter |
util | ✅ Most | Utility functions |
os | ✅ Complete | Operating system info |
child_process | ✅ Most | Child processes |
worker_threads | ✅ Most | Worker threads |
net | ✅ Most | Network sockets |
dns | ✅ Most | DNS resolution |
url | ✅ Complete | URL processing |
querystring | ✅ Complete | Query string |
zlib | ✅ Most | Compression |
assert | ✅ Complete | Assertions |
Partially Supported APIs
| Module | Status | Description |
|---|---|---|
cluster | ⚠️ Partial | Limited cluster mode support |
vm | ⚠️ Partial | Limited VM module support |
inspector | ⚠️ Partial | Debugger support |
trace_events | ❌ Unsupported | Trace events |
v8 | ❌ Unsupported | V8 specific APIs |
Using Node.js APIs
Import Methods
typescript
// Recommended: use node: prefix
import fs from "node:fs";
import path from "node:path";
import { EventEmitter } from "node:events";
// Also supported: without prefix
import crypto from "crypto";
import http from "http";File System
typescript
import fs from "node:fs";
import { readFile, writeFile } from "node:fs/promises";
// Synchronous read
const content = fs.readFileSync("./file.txt", "utf-8");
// Async read
const asyncContent = await readFile("./file.txt", "utf-8");
// Write file
await writeFile("./output.txt", "Hello, Bun!");
// Stream read
const stream = fs.createReadStream("./large-file.txt");
for await (const chunk of stream) {
console.log(chunk);
}HTTP Server
typescript
import http from "node:http";
// Node.js style HTTP server
const server = http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Hello from Node.js API!");
});
server.listen(3000, () => {
console.log("Server running at http://localhost:3000");
});Child Processes
typescript
import { spawn, exec } from "node:child_process";
// Use spawn
const child = spawn("ls", ["-la"]);
child.stdout.on("data", (data) => {
console.log(`stdout: ${data}`);
});
// Use exec
exec("echo 'Hello'", (error, stdout, stderr) => {
if (error) {
console.error(`Error: ${error}`);
return;
}
console.log(`Output: ${stdout}`);
});
// Use Promise (recommended)
import { execSync } from "node:child_process";
const result = execSync("echo 'Hello'").toString();Cryptography
typescript
import crypto from "node:crypto";
// Hash
const hash = crypto.createHash("sha256")
.update("Hello, World!")
.digest("hex");
console.log("SHA256:", hash);
// HMAC
const hmac = crypto.createHmac("sha256", "secret")
.update("message")
.digest("hex");
// Random bytes
const randomBytes = crypto.randomBytes(16);
console.log("Random bytes:", randomBytes.toString("hex"));
// UUID
const uuid = crypto.randomUUID();
console.log("UUID:", uuid);Migrating from Node.js
Step 1: Install Bun
bash
# Install Bun
curl -fsSL https://bun.sh/install | bash
# Verify installation
bun --versionStep 2: Switch Package Manager
bash
# Remove old dependencies
rm -rf node_modules package-lock.json yarn.lock pnpm-lock.yaml
# Install with Bun
bun installStep 3: Update package.json
json
{
"scripts": {
"start": "bun src/index.ts",
"dev": "bun --watch src/index.ts",
"build": "bun build src/index.ts --outdir dist",
"test": "bun test"
}
}Step 4: Check Compatibility
bash
# Try running
bun src/index.ts
# Check for errorsCommon Migration Issues
Issue 1: Module Not Found
typescript
// ❌ May throw error
import { something } from "obscure-package";
// ✅ Check package compatibility
bun pm ls obscure-packageIssue 2: Native Modules
typescript
// Some native Node.js modules may not be compatible
// Need to find alternatives or wait for Bun support
// For example: sharp image processing
// Check Bun support: https://bun.sh/docs/ecosystemIssue 3: Node.js Specific APIs
typescript
// ❌ Some Node.js specific APIs may not exist
process.binding("buffer");
// ✅ Use standard API alternatives
import { Buffer } from "node:buffer";Issue 4: __dirname and __filename
typescript
// In ESM, __dirname and __filename are not available
// ✅ Bun supports these
console.log(__dirname); // Available
console.log(__filename); // Available
// Or use import.meta
console.log(import.meta.dir); // Directory
console.log(import.meta.path); // File pathBun vs Node.js API Comparison
File Operations
typescript
// Node.js
import { readFile } from "fs/promises";
const content = await readFile("./file.txt", "utf-8");
// Bun (more concise)
const content = await Bun.file("./file.txt").text();HTTP Server
typescript
// Node.js
import http from "http";
const server = http.createServer((req, res) => {
res.writeHead(200);
res.end("Hello");
});
server.listen(3000);
// Bun (more concise)
Bun.serve({
port: 3000,
fetch: () => new Response("Hello"),
});Environment Variables
typescript
// Node.js
require("dotenv").config();
const value = process.env.MY_VAR;
// Bun (auto loads .env)
const value = Bun.env.MY_VAR;
// or
const value = process.env.MY_VAR;Running TypeScript
bash
# Node.js
npx ts-node app.ts
# or
npx tsx app.ts
# Bun (direct run)
bun app.tsUsing Bun Alternatives
Replacing Express
typescript
// Use Elysia (Bun-specific framework)
import { Elysia } from "elysia";
const app = new Elysia()
.get("/", () => "Hello Elysia")
.get("/user/:id", ({ params: { id } }) => `User ${id}`)
.post("/user", ({ body }) => body)
.listen(3000);
console.log(`Running at http://localhost:${app.server?.port}`);Replacing Jest
typescript
// Bun built-in testing
import { test, expect } from "bun:test";
test("addition", () => {
expect(1 + 1).toBe(2);
});Replacing webpack/esbuild
typescript
// Bun built-in bundling
await Bun.build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
minify: true,
});Progressive Migration
Strategy 1: Partial Bun Usage
json
{
"scripts": {
"start": "node dist/index.js",
"dev": "bun --watch src/index.ts",
"test": "bun test",
"build": "bun build src/index.ts --outdir dist"
}
}Strategy 2: Conditional Usage
typescript
// Detect runtime
const isBun = typeof Bun !== "undefined";
if (isBun) {
// Use Bun API
const content = await Bun.file("./data.txt").text();
} else {
// Use Node.js API
const { readFile } = await import("fs/promises");
const content = await readFile("./data.txt", "utf-8");
}Strategy 3: Abstraction Layer
typescript
// file-utils.ts
export async function readTextFile(path: string): Promise<string> {
if (typeof Bun !== "undefined") {
return Bun.file(path).text();
}
const { readFile } = await import("fs/promises");
return readFile(path, "utf-8");
}Compatibility Check Tools
Check Package Compatibility
bash
# View package compatibility status
# Visit https://bun.sh/ecosystemTest Run
bash
# Run project and observe errors
bun run start 2>&1 | head -50
# Run tests
bun testKnown Limitations
Incompletely Supported Features
- cluster module: Limited support
- vm module: Partial functionality
- Some Node.js internal APIs
- Specific native modules
Solutions
typescript
// If you encounter unsupported features
// 1. Check Bun docs for alternatives
// 2. Use polyfills
// 3. Conditional loading
// 4. Wait for Bun updates
// Example: conditional cluster usage
if (typeof Bun !== "undefined") {
// Use Bun's multi-process solution
} else {
// Use Node.js cluster
const cluster = require("cluster");
// ...
}Summary
This chapter covered:
- ✅ Bun's compatibility with Node.js APIs
- ✅ How to use Node.js modules
- ✅ Steps to migrate from Node.js
- ✅ Common migration issues and solutions
- ✅ Bun alternatives
- ✅ Progressive migration strategies
Next Steps
Continue reading Learning Resources for more learning materials.