bun by hoodini/ai-agents-skills
npx skills add https://github.com/hoodini/ai-agents-skills --skill bun使用 Bun 的一体化工具包构建和运行 JavaScript/TypeScript 应用程序。
# 安装 Bun (macOS, Linux, WSL)
curl -fsSL https://bun.sh/install | bash
# Windows
powershell -c "irm bun.sh/install.ps1 | iex"
# 创建新项目
bun init
# 直接运行 TypeScript (无需构建步骤!)
bun run index.ts
# 安装包 (比 npm 更快)
bun install
# 运行脚本
bun run dev
# 安装依赖
bun install # 从 package.json 安装所有依赖
bun add express # 添加依赖
bun add -d typescript # 添加开发依赖
bun add -g serve # 添加全局包
# 移除包
bun remove express
# 更新包
bun update
# 运行包二进制文件
bunx prisma generate # 类似 npx 但更快
bunx create-next-app
# 锁定文件
bun install --frozen-lockfile # CI 模式
# Bun 使用二进制锁定文件 (bun.lockb) - 速度更快
# 为兼容性生成 yarn.lock:
bun install --yarn
# 从其他锁定文件导入
bun install # 自动检测 package-lock.json, yarn.lock
# 运行任何文件
bun run index.ts # TypeScript
bun run index.js # JavaScript
bun run index.jsx # JSX
# 监视模式
bun --watch run index.ts
# 热重载
bun --hot run server.ts
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
// 文件 I/O (超快)
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); // MIME 类型
console.log(file.lastModified);
// 全局匹配文件
const glob = new Bun.Glob('**/*.ts');
for await (const file of glob.scan('.')) {
console.log(file);
}
// 简单服务器
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}`);
Bun.serve({
port: 3000,
// 主请求处理器
async fetch(req, server) {
const url = new URL(req.url);
// WebSocket 升级
if (url.pathname === '/ws') {
const upgraded = server.upgrade(req, {
data: { userId: '123' }, // 将数据附加到 socket
});
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);
}
}
// JSON API
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 处理器
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 });
},
});
const ws = new WebSocket('ws://localhost:3000/ws');
ws.onopen = () => {
ws.send('Hello, server!');
};
ws.onmessage = (event) => {
console.log('Received:', event.data);
};
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' },
]);
// 哈希密码
const hash = await Bun.password.hash('mypassword', {
algorithm: 'argon2id', // 或 'bcrypt'
memoryCost: 65536, // 64 MB
timeCost: 2,
});
// 验证密码
const isValid = await Bun.password.verify('mypassword', hash);
// 生成进程
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());
// Shell 命令
const { stdout } = Bun.spawn({
cmd: ['sh', '-c', 'echo $HOME'],
stdout: 'pipe',
});
// 哈希字符串
const hash = Bun.hash('hello world'); // Wyhash (快速)
// 加密哈希
const sha256 = new Bun.CryptoHasher('sha256');
sha256.update('data');
const digest = sha256.digest('hex');
// 一行代码
const md5 = Bun.CryptoHasher.hash('md5', 'data', 'hex');
// HMAC
const hmac = Bun.CryptoHasher.hmac('sha256', 'secret-key', 'data', 'hex');
# 为浏览器打包
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]'
const result = await Bun.build({
entrypoints: ['./src/index.ts'],
outdir: './dist',
minify: true,
sourcemap: 'external',
target: 'browser', // 'bun' | 'node' | '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);
}
// test.ts
import { describe, test, expect, beforeAll, afterAll, mock } from 'bun:test';
describe('数学运算', () => {
test('加法', () => {
expect(1 + 1).toBe(2);
});
test('数组包含', () => {
expect([1, 2, 3]).toContain(2);
});
test('对象匹配', () => {
expect({ name: 'Alice', age: 30 }).toMatchObject({ name: 'Alice' });
});
test('异步测试', async () => {
const result = await Promise.resolve(42);
expect(result).toBe(42);
});
test('抛出错误', () => {
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 API 开箱即用
import fs from 'fs';
import path from 'path';
import { createServer } from 'http';
import express from 'express';
// Bun 实现了 Node.js API
const data = fs.readFileSync('file.txt', 'utf-8');
const fullPath = path.join(__dirname, 'file.txt');
// Express 可用!
const app = express();
app.get('/', (req, res) => res.send('Hello!'));
app.listen(3000);
// Node.js 方式
import { readFile } from 'fs/promises';
const content = await readFile('file.txt', 'utf-8');
// Bun 方式 (更快)
const content = await Bun.file('file.txt').text();
// Node.js 加密
import crypto from 'crypto';
const hash = crypto.createHash('sha256').update('data').digest('hex');
// Bun 方式 (更快)
const hash = Bun.CryptoHasher.hash('sha256', 'data', 'hex');
// .env 文件支持 (内置,无需 dotenv!)
// .env
// DATABASE_URL=postgres://localhost/db
// API_KEY=secret
// 访问环境变量
const dbUrl = Bun.env.DATABASE_URL;
const apiKey = process.env.API_KEY; // 同样有效
// bunfig.toml 用于 Bun 配置
// [run]
// preload = ["./setup.ts"]
// Fetch (在 Bun 中优化)
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));
}
my-bun-project/
├── src/
│ ├── index.ts # 入口点
│ ├── routes/
│ │ └── api.ts
│ └── lib/
│ └── database.ts
├── tests/
│ └── index.test.ts
├── public/
│ └── static files
├── package.json
├── bunfig.toml # Bun 配置 (可选)
├── tsconfig.json
└── .env
[install]
# 默认使用精确版本
exact = true
# 注册表
registry = "https://registry.npmjs.org"
[run]
# 在 `bun run` 之前运行的脚本
preload = ["./instrumentation.ts"]
[test]
# 测试配置
coverage = true
coverageDir = "coverage"
[bundle]
# 默认打包配置
minify = true
sourcemap = "external"
| 操作 | Node.js | Bun | 速度提升 |
|---|---|---|---|
| 启动时间 | ~40ms | ~7ms | 5.7x |
| 包安装 | ~10s | ~1s | 10x |
| 文件读取 | 基准 | 更快 | 10x |
| HTTP 服务器 | 基准 | 更快 | 4x |
| SQLite | 外部 | 内置 | 3x |
| TypeScript | 需要编译 | 原生 | ∞ |
每周安装量
85
代码仓库
GitHub 星标数
134
首次出现
2026年1月22日
安全审计
安装于
opencode74
gemini-cli73
codex72
github-copilot68
cursor63
claude-code60
Build and run JavaScript/TypeScript applications with Bun's all-in-one toolkit.
# Install Bun (macOS, Linux, WSL)
curl -fsSL https://bun.sh/install | bash
# Windows
powershell -c "irm bun.sh/install.ps1 | iex"
# Create new project
bun init
# Run TypeScript directly (no build step!)
bun run index.ts
# Install packages (faster than npm)
bun install
# Run scripts
bun run dev
# Install dependencies
bun install # Install all from package.json
bun add express # Add dependency
bun add -d typescript # Add dev dependency
bun add -g serve # Add global package
# Remove packages
bun remove express
# Update packages
bun update
# Run package binaries
bunx prisma generate # Like npx but faster
bunx create-next-app
# Lockfile
bun install --frozen-lockfile # CI mode
# Bun uses binary lockfile (bun.lockb) - much faster
# To generate yarn.lock for compatibility:
bun install --yarn
# Import from other lockfiles
bun install # Auto-detects package-lock.json, yarn.lock
# Run any file
bun run index.ts # TypeScript
bun run index.js # JavaScript
bun run index.jsx # JSX
# Watch mode
bun --watch run index.ts
# Hot reload
bun --hot run server.ts
// File I/O (super fast)
const file = Bun.file('data.json');
const content = await file.text();
const json = await file.json();
const bytes = await file.arrayBuffer();
// Write files
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'));
// File metadata
const file = Bun.file('data.json');
console.log(file.size); // bytes
console.log(file.type); // MIME type
console.log(file.lastModified);
// Glob files
const glob = new Bun.Glob('**/*.ts');
for await (const file of glob.scan('.')) {
console.log(file);
}
// Simple 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}`);
Bun.serve({
port: 3000,
// Main request handler
async fetch(req, server) {
const url = new URL(req.url);
// WebSocket upgrade
if (url.pathname === '/ws') {
const upgraded = server.upgrade(req, {
data: { userId: '123' }, // Attach data to socket
});
if (upgraded) return undefined;
}
// Static files
if (url.pathname.startsWith('/static/')) {
const filePath = `./public${url.pathname}`;
const file = Bun.file(filePath);
if (await file.exists()) {
return new Response(file);
}
}
// JSON API
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 handlers
websocket: {
open(ws) {
console.log('Client connected:', ws.data.userId);
ws.subscribe('chat'); // Pub/sub
},
message(ws, message) {
// Broadcast to all subscribers
ws.publish('chat', message);
},
close(ws) {
console.log('Client disconnected');
},
},
// Error handling
error(error) {
return new Response(`Error: ${error.message}`, { status: 500 });
},
});
const ws = new WebSocket('ws://localhost:3000/ws');
ws.onopen = () => {
ws.send('Hello, server!');
};
ws.onmessage = (event) => {
console.log('Received:', event.data);
};
import { Database } from 'bun:sqlite';
const db = new Database('mydb.sqlite');
// Create table
db.run(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE
)
`);
// Insert
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
insert.run('Alice', 'alice@example.com');
// Query
const query = db.prepare('SELECT * FROM users WHERE id = ?');
const user = query.get(1);
// All results
const allUsers = db.prepare('SELECT * FROM users').all();
// Transaction
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' },
]);
// Hash password
const hash = await Bun.password.hash('mypassword', {
algorithm: 'argon2id', // or 'bcrypt'
memoryCost: 65536, // 64 MB
timeCost: 2,
});
// Verify password
const isValid = await Bun.password.verify('mypassword', hash);
// Spawn process
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);
// Spawn sync
const result = Bun.spawnSync(['echo', 'hello']);
console.log(result.stdout.toString());
// Shell command
const { stdout } = Bun.spawn({
cmd: ['sh', '-c', 'echo $HOME'],
stdout: 'pipe',
});
// Hash strings
const hash = Bun.hash('hello world'); // Wyhash (fast)
// Crypto hashes
const sha256 = new Bun.CryptoHasher('sha256');
sha256.update('data');
const digest = sha256.digest('hex');
// One-liner
const md5 = Bun.CryptoHasher.hash('md5', 'data', 'hex');
// HMAC
const hmac = Bun.CryptoHasher.hmac('sha256', 'secret-key', 'data', 'hex');
# Bundle for browser
bun build ./src/index.ts --outdir ./dist
# Bundle options
bun build ./src/index.ts \
--outdir ./dist \
--minify \
--sourcemap \
--target browser \
--splitting \
--entry-naming '[dir]/[name]-[hash].[ext]'
const result = await Bun.build({
entrypoints: ['./src/index.ts'],
outdir: './dist',
minify: true,
sourcemap: 'external',
target: 'browser', // 'bun' | 'node' | '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);
}
// test.ts
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');
});
});
// Mocking
const mockFn = mock(() => 'mocked');
mockFn();
expect(mockFn).toHaveBeenCalled();
// Mock modules
mock.module('./database', () => ({
query: mock(() => [{ id: 1 }]),
}));
# Run tests
bun test
# Watch mode
bun test --watch
# Specific file
bun test user.test.ts
# Coverage
bun test --coverage
// Most Node.js APIs work out of the box
import fs from 'fs';
import path from 'path';
import { createServer } from 'http';
import express from 'express';
// Bun implements Node.js APIs
const data = fs.readFileSync('file.txt', 'utf-8');
const fullPath = path.join(__dirname, 'file.txt');
// Express works!
const app = express();
app.get('/', (req, res) => res.send('Hello!'));
app.listen(3000);
// Node.js way
import { readFile } from 'fs/promises';
const content = await readFile('file.txt', 'utf-8');
// Bun way (faster)
const content = await Bun.file('file.txt').text();
// Node.js crypto
import crypto from 'crypto';
const hash = crypto.createHash('sha256').update('data').digest('hex');
// Bun way (faster)
const hash = Bun.CryptoHasher.hash('sha256', 'data', 'hex');
// .env file support (built-in, no dotenv needed!)
// .env
// DATABASE_URL=postgres://localhost/db
// API_KEY=secret
// Access env vars
const dbUrl = Bun.env.DATABASE_URL;
const apiKey = process.env.API_KEY; // Also works
// bunfig.toml for Bun config
// [run]
// preload = ["./setup.ts"]
// Fetch (optimized in Bun)
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();
// Streaming response
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));
}
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
[install]
# Use exact versions by default
exact = true
# Registry
registry = "https://registry.npmjs.org"
[run]
# Scripts to run before `bun run`
preload = ["./instrumentation.ts"]
[test]
# Test configuration
coverage = true
coverageDir = "coverage"
[bundle]
# Default bundle config
minify = true
sourcemap = "external"
| 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 | ∞ |
Weekly Installs
85
Repository
GitHub Stars
134
First Seen
Jan 22, 2026
Security Audits
Gen Agent Trust HubFailSocketPassSnykWarn
Installed on
opencode74
gemini-cli73
codex72
github-copilot68
cursor63
claude-code60
Flutter应用架构设计指南:分层结构、数据层实现与最佳实践
4,800 周安装