Chapter 02

Bun 核心特性深度

解锁 Bun 的全部潜力:从极速包管理到内置 SQLite,从 Shell 脚本到文件 API

Bun 的四大身份

理解 Bun 的关键在于:它不只是"另一个 Node.js",而是一个完整工具链,由四个独立的子系统组成:

bun install — 极速包管理

工作原理

Bun 的包管理之所以快,核心在于全局内容寻址缓存

# Bun 的全局缓存目录
~/.bun/install/cache/

# 当你 install 一个包:
# 1. 检查缓存是否已有该版本(按 hash 寻址)
# 2. 缓存命中:直接 hardlink 或 symlink 到 node_modules
# 3. 缓存未命中:下载、提取、写入缓存,然后 link
# 4. 全程并发执行,无依次下载的串行等待

常用命令

# 安装 package.json 中所有依赖
bun install

# 添加依赖
bun add hono zod
bun add -d typescript @types/bun  # 开发依赖
bun add -g http-server             # 全局安装

# 删除依赖
bun remove lodash

# 更新依赖
bun update

# 运行 package.json scripts
bun run dev
bun run build
bun run test

bun.lock 格式

Bun 1.2+ 引入了二进制格式的 bun.lock 文件,取代了之前的 bun.lockb(也是二进制,但现在改为文本):

# bun.lock 是人类可读的文本格式(类似 yarn.lock)
# 应该提交到 git,确保团队和 CI 使用完全一致的依赖版本

# 与 npm/yarn 的互操作
# Bun 会读取 package-lock.json / yarn.lock 进行兼容
bun install --frozen-lockfile   # CI 环境:锁定安装,不更新

workspaces 支持:Bun 完全支持 npm workspaces(monorepo),在 package.json 中定义 "workspaces": ["packages/*"] 即可,bun install 自动处理所有子包的依赖提升。

bun build — 内置打包器

// build.ts — 构建脚本示例
const result = await Bun.build({
  entrypoints: ['./src/index.ts'],
  outdir: './dist',
  target: 'bun',        // 或 'node' | 'browser'
  format: 'esm',
  minify: true,
  splitting: true,       // 代码分割
  sourcemap: 'linked',
  external: ['pg', 'redis'],  // 不打包这些模块
});

if (!result.success) {
  console.error(result.logs);
  process.exit(1);
}

console.log(`打包完成:${result.outputs.length} 个文件`);

Bun Shell — 内置 Shell 脚本

Bun Shell($\`command\` 语法)是 Bun 1.0 最惊艳的特性之一,让你在 TypeScript 中写 Shell 脚本,跨平台(包括 Windows):

import { $ } from 'bun';

// 基础用法
await $`echo Hello, World!`;

// 获取输出
const result = await $`ls -la`.text();
console.log(result);

// 插值(自动转义,防注入)
const filename = 'my file.txt';
await $`cat ${filename}`;  // 安全:会转义空格

// 管道
const lines = await $`cat package.json | grep name`.lines();

// 错误处理
const output = await $`git status --short`.quiet().nothrow();
if (output.exitCode !== 0) {
  console.log('不在 git 仓库中');
}

// 环境变量
await $`echo $HOME`.env({ HOME: '/custom/home' });

// 实际应用:构建脚本
async function deploy() {
  console.log('开始构建...');
  await $`bun run build`;
  await $`docker build -t my-app:latest .`;
  await $`docker push my-app:latest`;
  console.log('部署完成 ✓');
}

deploy();

告别 shelljs:Bun Shell 是 shelljs、execa 等包的内置替代品。最大优势是跨平台——同样的脚本在 macOS、Linux、Windows 上都能运行,不需要 WSL。

内置 SQLite

Bun 内置了高性能的 SQLite 支持(通过 bun:sqlite),无需安装任何 npm 包,性能比 better-sqlite3 快约 3 倍:

import { Database } from 'bun:sqlite';

// 打开/创建数据库
const db = new Database('mydb.sqlite');
// 内存数据库:new Database(':memory:')

// 建表
db.exec(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  )
`);

// 预编译语句(推荐,防 SQL 注入)
const insertUser = db.prepare(`
  INSERT INTO users (name, email) VALUES ($name, $email)
`);

// 插入
insertUser.run({ $name: '张三', $email: 'zhang@example.com' });

// 查询单行
const getUser = db.prepare('SELECT * FROM users WHERE id = $id');
const user = getUser.get({ $id: 1 });

// 查询多行
const getAllUsers = db.prepare('SELECT * FROM users ORDER BY created_at DESC');
const users = getAllUsers.all();

// 事务(性能关键:批量操作用事务包裹,速度提升数十倍)
const insertMany = db.transaction((users: Array<{name: string, email: string}>) => {
  for (const user of users) {
    insertUser.run({ $name: user.name, $email: user.email });
  }
});

insertMany.immediate([
  { name: '李四', email: 'li@example.com' },
  { name: '王五', email: 'wang@example.com' },
]);

// 关闭连接
db.close();

何时用内置 SQLite vs Prisma:内置 SQLite 适合本地工具、测试数据、中小型应用(用户量 < 10万)。大型应用推荐 PostgreSQL + Prisma ORM(见第5章)。SQLite 本身没有问题,但缺乏并发写入能力,不适合高写入负载。

文件读写 API

Bun 提供了比 Node.js fs 模块更简洁的文件 API:

Node.js fs 模块
import fs from 'node:fs/promises';

// 读取文件
const text = await fs.readFile(
  './data.json', 'utf8'
);

// 写入文件
await fs.writeFile(
  './output.txt',
  'Hello World',
  'utf8'
);

// 追加内容
await fs.appendFile(
  './log.txt', 'new line\n'
);
Bun 文件 API
// Bun.file() 返回 BunFile 对象(惰性)
const file = Bun.file('./data.json');

// 读取为文本
const text = await file.text();
// 读取为 JSON(自动解析)
const json = await file.json();
// 读取为 ArrayBuffer
const buf = await file.arrayBuffer();

// 写入(极速,使用系统调用优化)
await Bun.write(
  './output.txt', 'Hello World'
);

BunFile 的惰性求值

Bun.file() 不会立即读取文件,只是创建一个引用。只有调用 .text().json() 等方法才真正读取——这使得传递文件引用非常高效:

const file = Bun.file('./large-file.bin');

console.log(file.size);       // 文件大小(字节),不读取内容
console.log(file.type);       // MIME 类型(自动推断): "application/octet-stream"
console.log(file.name);       // 文件路径
console.log(await file.exists());  // 是否存在

// 将文件作为 HTTP 响应体(零拷贝)
const server = Bun.serve({
  port: 3000,
  fetch(req) {
    // Bun 会使用 sendfile() 系统调用,零拷贝传输
    return new Response(Bun.file('./index.html'));
  }
});

Bun.serve — 内置 HTTP 服务器

Bun 内置了基于 uWebSockets.js 的超高性能 HTTP 服务器,无需任何框架即可使用:

import { type Server } from 'bun';

const server = Bun.serve({
  port: 3000,
  hostname: '0.0.0.0',

  // 每个请求调用 fetch
  async fetch(req: Request, server: Server) {
    const url = new URL(req.url);

    if (url.pathname === '/') {
      return new Response('Hello from Bun!');
    }

    if (url.pathname === '/json') {
      return Response.json({ message: 'Hello', time: Date.now() });
    }

    // 读取请求体
    if (req.method === 'POST' && url.pathname === '/echo') {
      const body = await req.json();
      return Response.json(body);
    }

    return new Response('Not Found', { status: 404 });
  },

  // 错误处理
  error(err) {
    return new Response(`Error: ${err.message}`, { status: 500 });
  }
});

console.log(`服务器运行在 http://localhost:${server.port}`);

环境变量与 .env 支持

Bun 原生支持 .env 文件,无需 dotenv 包:

# .env 文件(自动加载)
DATABASE_URL=postgresql://localhost:5432/mydb
JWT_SECRET=your-secret-key
PORT=3000
NODE_ENV=development
// TypeScript 中直接访问
const port = Number(process.env.PORT ?? '3000');
const dbUrl = process.env.DATABASE_URL!;

// Bun 也支持类型安全的环境变量(通过 TypeScript 声明)
// 在 src/types/env.d.ts 中:
declare namespace NodeJS {
  interface ProcessEnv {
    DATABASE_URL: string;
    JWT_SECRET: string;
    PORT?: string;
    NODE_ENV: 'development' | 'production' | 'test';
  }
}

优先级:Bun 加载 .env 的优先级为:.env.local > .env.[NODE_ENV] > .env。切记将 .env.local 加入 .gitignore.env 只存放公开的默认值。

Node.js 兼容性

Bun 目标是实现完整的 Node.js API 兼容,2024 年的兼容率已超过 95%:

Node.js 模块Bun 兼容状态
node:fs, node:path✅ 完全兼容
node:http, node:https✅ 完全兼容
node:crypto✅ 完全兼容
node:stream✅ 基本兼容
node:worker_threads✅ 支持
node:child_process✅ 支持
Native Addons (.node)⚠️ 部分支持(Node-API/napi)