正在加载,请稍候…

Bun Runtime: Migrating Node.js Apps for 3x Performance

Migrate Node.js applications to Bun — compatibility layer, built-in bundler, SQLite, hot reload, test runner, and benchmarks vs Node.js and Deno.

What is Bun?

Bun is an all-in-one JavaScript runtime built on JavaScriptCore (Safari's engine). It ships a runtime, bundler, test runner, and package manager in one binary.

Installation and Migration

# Install Bun
curl -fsSL https://bun.sh/install | bash

# Run a Node.js app with Bun (most apps work as-is)
bun run src/index.ts  # TypeScript natively!

# Replace npm scripts
bun install           # ~25x faster than npm
bun run dev
bun run build

Bun's Built-in HTTP Server

// Much faster than Express/Fastify
const server = Bun.serve({
  port: 3000,
  async fetch(req) {
    const url = new URL(req.url)
    
    if (url.pathname === '/') {
      return new Response('Hello from Bun!')
    }
    
    if (url.pathname === '/json') {
      return Response.json({ message: 'Hello', timestamp: Date.now() })
    }
    
    return new Response('Not found', { status: 404 })
  },
})

console.log(`Listening on port ${server.port}`)

Built-in SQLite

import { Database } from 'bun:sqlite'

const db = new Database('myapp.db')

// Create table
db.run(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL
  )
`)

// Prepared statements (fast, safe)
const insertUser = db.prepare('INSERT INTO users (name, email) VALUES ($name, $email)')
const getUser = db.prepare('SELECT * FROM users WHERE id = $id')
const getAllUsers = db.prepare('SELECT * FROM users LIMIT $limit OFFSET $offset')

// Run
insertUser.run({ $name: 'Alice', $email: 'alice@example.com' })
const user = getUser.get({ $id: 1 })
const users = getAllUsers.all({ $limit: 20, $offset: 0 })

Bun Test Runner

import { describe, test, expect, beforeEach } from 'bun:test'

describe('UserService', () => {
  let service: UserService

  beforeEach(() => {
    service = new UserService(mockDb)
  })

  test('creates a user', async () => {
    const user = await service.create({ name: 'Bob', email: 'bob@test.com' })
    expect(user.id).toBeDefined()
    expect(user.name).toBe('Bob')
  })

  test('throws on duplicate email', async () => {
    await service.create({ name: 'Bob', email: 'bob@test.com' })
    expect(() =>
      service.create({ name: 'Bob 2', email: 'bob@test.com' })
    ).toThrow('Email taken')
  })
})
bun test                    # Run all tests
bun test --watch            # Watch mode
bun test --coverage         # Coverage report

Bun Bundler

// build.ts
await Bun.build({
  entrypoints: ['./src/index.ts'],
  outdir: './dist',
  target: 'bun',
  minify: true,
  sourcemap: 'external',
  splitting: true,
})

Performance Comparison

Benchmark Bun Node.js 22 Deno
HTTP req/s ~120k ~68k ~72k
Install deps 1.2s 31s N/A
Test run 0.3s 2.1s 0.8s
Startup time 2ms 40ms 50ms

Migration Gotchas

  • __filename and __dirname work in Bun (not just ESM)
  • Most npm packages work; some native addons may not
  • node: prefix imports work: import fs from 'node:fs'
  • process.env works as expected