Bun は「Runtime・Package Manager・Bundler・Test Runnerを 1 バイナリに統合した、Zig 製の高速 JavaScript 実行環境」です。2023 年に 1.0 が出た頃はまだ尖ったツールでしたが、2025 年初頭の Bun 1.2 で Node.js テストスイートの 90% 以上をパスし、2025 年 10 月の Bun 1.3 で Redis クライアント・Package Catalog・ワークスペース Isolated Install が入った結果、2026 年は「本番で使える現実解」として評価が固まりました。
この記事では 2026 年 4 月時点の Bun 1.3 系を前提に、bun install / bun run の基本、Bun.serve / Bun.sql / Bun.redis / Bun.s3 / Bun.$ といった組込み API、bun test と bun build、Workspace と Package Catalogs、Node.js からの移行手順、本番運用の勘所までを一気通貫で解説します。TypeScript サンプルで全機能を実戦的に示すので、既存 Node.js プロジェクトに Bun を段階導入したい場合のリファレンスとしても使える内容です。
- 2026 年 4 月時点の Bun バージョン整理
- インストールとプロジェクト作成
- bun install ── 30% 高速の次世代パッケージマネージャー
- bun run ── Node や ts-node 不要で TS を直接実行
- Bun.serve ── 組込み HTTP / WebSocket サーバー
- Bun.sql ── ネイティブ Postgres クライアント
- Bun.redis ── 組込み Redis クライアント(1.3+)
- Bun.s3 ── ネイティブ S3 / R2 / GCS クライアント
- Bun.$ ── クロスプラットフォームのシェルスクリプト
- bun test ── Jest 互換の組込みテストランナー
- bun build ── バンドラーとしての Bun
- ゼロ設定フロントエンド開発(Bun 1.3+)
- Node.js から Bun への移行手順
- 本番デプロイのパターン
- 落とし穴と注意点
- よくある質問
- まとめ
2026 年 4 月時点の Bun バージョン整理
Bun は年 2 回ペースでメジャーマイナーが更新され、その間にも頻繁にパッチがリリースされます。2026 年 4 月時点で新規に採用するなら Bun 1.3.x 系が推奨です。
| リリース | 時期 | 主なハイライト |
|---|---|---|
| Bun 1.2 | 2025 年 1 月 | Node.js 互換 90%+・bun.lock(JSONC 形式)・Bun.sql(Postgres)・Bun.s3・静的ルート・CSS バンドル・UDP Socket・5× / 3× / 50% の個別高速化 |
| Bun 1.3 | 2025 年 10 月 | Bun.redis・Package Catalogs・Workspace Isolated Installs・ゼロ設定フロントエンド開発・Async Stack Traces・VS Code テスト統合 |
| 推奨 | 2026 年 4 月 | Bun 1.3 系。Node.js 置換用途・新規プロジェクトともにこの系列 |
node + npm(or pnpm) + tsx + esbuild + jest を 1 バイナリに置き換える存在です。起動が速い・TS を直接動かせる・型エラーは tsc に任せられる、という 3 点がベース。Bun.sql / Bun.redis で接続系ライブラリも追加不要になります。インストールとプロジェクト作成
# 公式 curl(/usr/local/bin に 1 バイナリで入る) curl -fsSL https://bun.sh/install | bash # Homebrew でも可 brew install oven-sh/bun/bun # Windows(ネイティブサポート。PowerShell) powershell -c "irm bun.sh/install.ps1 | iex" # バージョン確認 bun --version # 1.3.x # 更新 bun upgrade
bun init my-app cd my-app # 生成される構成 # ├── .gitignore # ├── bun.lock ← JSONC 形式のロックファイル # ├── index.ts # ├── package.json # ├── README.md # └── tsconfig.json # そのまま実行 bun run index.ts
既存 Node.js プロジェクトを Bun 化する最小手順
# 1) npm / pnpm / yarn の成果物を退避(バックアップ) mv node_modules node_modules.bak mv package-lock.json package-lock.json.bak # あれば # 2) Bun で再インストール(bun.lock が生成される) bun install # 3) スクリプトはそのまま動く bun run dev
"scripts" を bun run <name> で実行します。Node.js 向けに書いていた dev / build / test などのスクリプトは改変不要で動くケースが大半です。bun install ── 30% 高速の次世代パッケージマネージャー
bun install は pnpm の結果と互換な node_modules を生成しつつ、インストール速度は npm の数倍〜 10 倍に達します。bun.lock は JSONC 形式で PR レビューも merge conflict 解消も容易です。
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "my-app",
"dependencies": { "hono": "4.9.1" }
}
},
"packages": [
["hono@4.9.1", /* tarball */, "sha512-..."],
["@types/bun@1.3.0", /* devDep */, "sha512-..."]
]
}
基本コマンド一覧
# すべての依存をインストール bun install # 省略可: bun i # 追加(--save, --save-dev, --save-peer 等も対応) bun add hono bun add -d vitest # devDependencies # 削除 bun remove hono # 依存更新状況を可視化 bun outdated # 特定ライブラリだけ更新 bun update zod # ローカル npm パッケージをパブリッシュ bun publish # パッチ適用(@types/node のバグ回避等) bun patch @types/node bun patch --commit @types/node
Package Catalogs(Bun 1.3+)── モノレポでバージョンを 1 箇所に集約
{
"workspaces": {
"packages": ["apps/*", "packages/*"]
},
"catalogs": {
"react19": {
"react": "19.2.0",
"react-dom": "19.2.0"
}
}
}
{
"dependencies": {
"react": "catalog:react19",
"react-dom": "catalog:react19"
}
}
Workspace Isolated Installs(Bun 1.3+)
Bun 1.3 以降、Workspace は未宣言の依存を参照できない(Isolated Install)のがデフォルトになりました。「別パッケージが入れているから偶然動いている」型のバグを静的に排除します。
bun run ── Node や ts-node 不要で TS を直接実行
# .ts / .tsx を直接実行(tsc / ts-node 不要) bun run index.ts # JSX でも OK bun run App.tsx # --hot で擬似 HMR(ファイル変更で関数単位再読み込み) bun --hot index.ts # --watch はプロセス再起動(nodemon 相当) bun --watch index.ts # package.json の scripts bun run dev # == "dev" スクリプト実行 # 複数 workspace で並列実行(1.3+) bun run --filter="*" dev
--hot と --watch の使い分け: --hot はプロセスを再起動せず状態を保ったままモジュールを差し替える擬似 HMR。API サーバーでは接続プールや長時間処理を維持したい場面で有効。--watch はプロセスごと再起動なので、副作用のあるグローバル状態をクリアしたいシーンで使います。Bun.serve ── 組込み HTTP / WebSocket サーバー
Bun.serve は標準 Web APIs(Request / Response)を採用したネイティブ実装の HTTP サーバーです。Node.js の http より同じ Hello World で 3× 以上スループットが出ます。
import { serve } from "bun";
const server = serve({
port: 3000,
// 静的ルート: Bun がキャッシュして高速配信
static: {
"/health": new Response("ok"),
"/version": Response.json({ bun: Bun.version }),
"/legacy": Response.redirect("/new", 301),
},
// 動的ハンドラ
async fetch(req) {
const url = new URL(req.url);
if (url.pathname === "/hello") {
return Response.json({ message: "hello bun" });
}
return new Response("Not Found", { status: 404 });
},
});
console.log(`listening on ${server.url}`);
// ランタイム差し替え(コード変更なしで静的ルート更新)
setInterval(() => {
server.reload({
static: { "/": new Response(`updated at ${new Date().toISOString()}`) },
});
}, 1000);
serve({
port: 3001,
fetch(req, server) {
if (server.upgrade(req)) return; // WebSocket にアップグレード
return new Response("HTTP route");
},
websocket: {
open(ws) { ws.send("hello"); },
message(ws, msg) { ws.send(`echo: ${msg}`); },
close(ws) { console.log("closed"); },
},
});
Bun.sql ── ネイティブ Postgres クライアント
Bun.sql は postgres.js 互換の API を Zig で実装したネイティブクライアントです。タグ付きテンプレートリテラルで SQL インジェクションを構造的に防ぎ、プリペアドステートメントとクエリパイプライニングが自動で効きます。Node + pg の構成より 50% 高速という測定結果が報告されています。
import { sql } from "bun";
// 環境変数から DATABASE_URL を拾う
// postgres://user:pass@host:5432/db
type User = { id: number; name: string; age: number };
// INSERT(複数行)
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 65 },
];
await sql`INSERT INTO users ${sql(users)}`;
// SELECT
const seniors = await sql<User[]>`
SELECT id, name, age
FROM users
WHERE age >= ${65}
`;
// UPDATE(動的 WHERE)
await sql`
UPDATE users SET name = ${"Alice2"}
WHERE id = ${seniors[0].id}
`;
// DELETE
await sql`DELETE FROM users WHERE age < ${20}`;
// 明示的な接続プール・型パラメータ
const db = new Bun.SQL({
url: process.env.DATABASE_URL,
max: 10, // プール上限
idle_timeout: 30,
connection_timeout: 5,
});
const rows = await db`SELECT 1 AS ok`;
トランザクション
await sql.begin(async (tx) => {
await tx`UPDATE accounts SET balance = balance - 100 WHERE id = ${1}`;
await tx`UPDATE accounts SET balance = balance + 100 WHERE id = ${2}`;
// コールバック内で throw したら自動 ROLLBACK、正常終了で COMMIT
});
Bun.redis ── 組込み Redis クライアント(1.3+)
Bun 1.3 で追加された Bun.redis は、ioredis / redis ライブラリ不要で Redis / Valkey に接続できるネイティブクライアントです。66 個以上のコマンドを型付きでサポートし、未対応コマンドは redis.send() でエスケープ可能です。
import { redis } from "bun";
// REDIS_URL 環境変数から自動接続
// redis://default:pass@host:6379
await redis.set("user:1", JSON.stringify({ id: 1, name: "Alice" }));
await redis.expire("user:1", 60);
const raw = await redis.get("user:1");
const user = raw ? JSON.parse(raw) : null;
// インクリメント
const count = await redis.incr("visits:2026-04-22");
// 未対応コマンドは send() でエスケープ
const info = await redis.send("INFO", ["server"]);
// 並列発行(内部で自動パイプライニング)
const [ok1, ok2, val] = await Promise.all([
redis.set("a", "1"),
redis.set("b", "2"),
redis.get("a"),
]);
Bun.s3 ── ネイティブ S3 / R2 / GCS クライアント
Bun.s3 は AWS S3 / Cloudflare R2 / Google Cloud Storage に対応した組込みオブジェクトストレージクライアントです。Node.js + AWS SDK より 5 倍高速で、Bun.file と同じ API で扱えます。
import { s3 } from "bun";
// 環境変数 S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY / S3_BUCKET / S3_ENDPOINT など
// Cloudflare R2 なら S3_ENDPOINT に R2 エンドポイントを指定
// 読み込み
const text = await s3.file("reports/2026-04.md").text();
const bin = await s3.file("images/logo.png").arrayBuffer();
// 書き込み
await s3.file("logs/app.log").write("hello\n");
// 大きなファイル(ストリーミング)
const writer = s3.file("large-export.csv").writer();
for await (const chunk of generateChunks()) writer.write(chunk);
await writer.end();
// 署名付き URL(期限付き共有リンク)
const url = s3.presign("private/doc.pdf", {
expiresIn: 3600, // 1h
acl: "public-read",
});
// Bun.serve の静的ルートにそのまま流せる
serve({
static: { "/favicon.ico": s3.file("public/favicon.ico") },
fetch() { return new Response("ok"); },
});
Bun.$ ── クロスプラットフォームのシェルスクリプト
Bun.$ は TS / JS からシェルコマンドを実行する zx ライクな組込みシェルです。Bash を持たない Windows でも同じ書き方で動きます(Zig 実装の POSIX 互換レイヤ)。
import { $ } from "bun";
// 基本実行(終了コードが非 0 なら throw)
await $`echo "hello"`;
// 変数を安全に展開(シェルインジェクション対策込み)
const branch = "main";
await $`git checkout ${branch}`;
// stdout を文字列として受け取る
const tag = (await $`git describe --tags --abbrev=0`.text()).trim();
// JSON として
const pkg = await $`cat package.json`.json();
// パイプも書ける
await $`ls -la | grep -v node_modules`;
// 終了コード制御
const res = await $`test -d dist`.nothrow();
if (res.exitCode !== 0) await $`mkdir -p dist`;
// 環境変数注入
await $`npm publish`.env({ NPM_TOKEN: process.env.NPM_TOKEN });
// カレントディレクトリ変更
await $`pwd`.cwd("/tmp");
$\`rm -rf ${userInput}\` は Bun が自動でクォートしますが、自前で文字列連結して $\`rm -rf \${str}\` のように $\{\} を JS 側で組み立てると無効化できてしまいます。必ずテンプレートリテラルの埋め込み構文を使ってください。bun test ── Jest 互換の組込みテストランナー
bun test は Jest / Vitest 互換の API を持つ高速テストランナーです。TS / JSX をそのまま走らせ、Jest の 10 倍以上の速度で動くケースも珍しくありません。
import { expect, test, describe, mock } from "bun:test";
describe("math", () => {
test("add", () => {
expect(2 + 3).toBe(5);
});
test("floating point", () => {
expect(0.1 + 0.2, "丸め誤差チェック").toBeCloseTo(0.3);
});
test("inline snapshot", () => {
const config = { env: "prod", retries: 3 };
expect(config).toMatchInlineSnapshot(`
{
"env": "prod",
"retries": 3,
}
`);
});
});
// モック
const fetchMock = mock(() => Promise.resolve({ ok: true }));
expect(fetchMock).toHaveReturned();
// フィルタ: このテストだけ走らせたい時
test.only("focused", () => {
expect(1).toBe(1);
});
# JUnit 形式でレポート出力(CI 向け) bun test --reporter=junit --reporter-outfile=test-results.xml # カバレッジ計測(lcov 出力) bun test --coverage --coverage-reporter=lcov # 単一ファイル・パターン指定 bun test src/auth/*.test.ts bun test --test-name-pattern="should login" # VS Code テスト統合(1.3+) # Bun: Test エクスプローラに直接統合されるようになった
bun build ── バンドラーとしての Bun
bun build は esbuild 相当の速度と webpack 的な機能を併せ持つバンドラーです。ブラウザ向け・Node 向け・Bun 向け・Single-file executable まで、同じコマンドで切り替えます。
# ブラウザ向けにバンドル(Tree-shaking 込み) bun build ./src/main.tsx --outdir ./dist --target browser --minify # Node.js 向けバンドル bun build ./src/server.ts --outdir ./dist --target node # Bun 向けスタンドアロンバイナリ(--compile) bun build --compile ./src/cli.ts --outfile mycli # クロスコンパイル(1.2+) bun build --compile --target=bun-linux-x64 ./src/cli.ts --outfile mycli-linux bun build --compile --target=bun-windows-x64 ./src/cli.ts --outfile mycli.exe bun build --compile --target=bun-darwin-arm64 ./src/cli.ts --outfile mycli-mac # Bytecode キャッシュ付き(起動高速化) bun build --bytecode --compile ./src/cli.ts --outfile mycli # 環境変数を注入(PUBLIC_ プレフィックスのみ) bun build ./src/app.tsx --env="PUBLIC_*" # console.* を落とす bun build ./src/app.ts --drop=console --minify # 外部パッケージを bundle 対象外にする bun build ./src/server.ts --packages=external
--compile を付けると Bun ランタイム本体を含む 1 ファイルの実行可能バイナリ(Linux / macOS / Windows)が生成されます。Docker イメージや配布用 CLI を「Node.js を入れなくても動く単一ファイル」にできるので、運用が激変します。ゼロ設定フロントエンド開発(Bun 1.3+)
Bun 1.3 では HTML インポートとフロントエンド用組込みサーバーが統合され、Vite 相当のことを設定ファイルなしで開始できます。
// server.ts
import homepage from "./index.html";
Bun.serve({
routes: {
"/": homepage, // HTML/CSS/JS/TSX を自動バンドル
"/api/hello": () => Response.json({ hello: "bun" }),
},
development: true, // HMR 有効
});
// index.html 側で <script src="./app.tsx"></script> と書けば
// 自動的に TSX がバンドルされてブラウザに配信される
Node.js から Bun への移行手順
2026 年時点で fs / path / stream / http / http2 / events / url / os / crypto / buffer など主要モジュールは 90% 以上の互換性があります。移行は段階的に、本番ワークロードでベンチを取りながら進めるのが安全です。
| ステップ | 内容 | 注意点 |
|---|---|---|
| ① ローカル CI で並走 | bun install / bun test を Node.js と並行実行 |
差分テストを試す。失敗する箇所だけリスト化 |
| ② スクリプト層から置換 | package.json の scripts を bun run に置き換え |
CI の実行時間が 30〜70% 短縮する事例多数 |
| ③ テストを bun test に移行 | Jest / Vitest を段階的に bun test へ | スナップショット互換性に注意(Jest 形式は変換が必要) |
| ④ 本番 Runtime を Bun に | Docker ベースイメージを oven/bun に |
N-API を使う依存(sharp 等)は先にテスト |
| ⑤ ネイティブ API に置換 | pg → Bun.sql、ioredis → Bun.redis、aws-sdk → Bun.s3 |
各段階でベンチ取得 |
sharp、better-sqlite3、bcrypt などの C++ 依存は 1.3 で多くが動作しますが、CI で必ず動作確認してから本番投入してください。node-gyp ビルドが絡むパッケージは特にリスクが残ります。本番デプロイのパターン
Docker で動かす
FROM oven/bun:1.3-alpine AS deps WORKDIR /app COPY package.json bun.lock ./ RUN bun install --frozen-lockfile --production FROM oven/bun:1.3-alpine WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . ENV NODE_ENV=production EXPOSE 3000 CMD ["bun", "run", "src/server.ts"]
Single-file executable で配布
# CI で各 OS ターゲットを build bun build --compile --target=bun-linux-x64 --minify --bytecode \ ./src/server.ts --outfile server-linux # 実行(コンテナにも Node.js 不要) scp server-linux user@host:/opt/app/ ssh user@host "/opt/app/server-linux"
サーバーレス・エッジ
Bun は Cloudflare Workers や Vercel Edge Functions のような専用エッジランタイムには乗りませんが、「自前で Bun.serve を立てる」軽量エッジ的運用には最適です。代替として Hono を Cloudflare Workers に乗せたい場合は、既存の TypeScript × Hono 完全ガイド が参考になります。
落とし穴と注意点
N-API 依存で動かないパッケージが残る
node-gyp を使う C++ アドオン(古い canvas / 一部の DB ドライバ)は 1.3 でも一部動かない場合があります。CI で実際に bun install → bun test が通るかを確認してから本番投入してください。
プロセスモデルと Worker
Bun は単一プロセス・シングルイベントループがベースです。CPU バウンドな処理は Worker(Web Workers 互換 API)に切り出す設計が推奨されます。Node.js の worker_threads 互換モードもありますが、パフォーマンスが出る API はネイティブ Web Workers のほうです。
一部の環境変数プレフィックス運用が違う
フロントエンド向けバンドル時に注入する環境変数は PUBLIC_* が規約。Vite の VITE_* や Next.js の NEXT_PUBLIC_* と混ぜると事故るため、チーム内の命名を統一してください。
bun.lock を消さない
Bun は bun.lock があれば決定論的にインストールします。手癖で rm -rf node_modules package-lock.json yarn.lock などをやって bun.lock まで消してしまうとバージョンが微妙にずれる事故が起きます。bun install --frozen-lockfile を CI で徹底してください。
Bun.sql の接続プールは暗黙
デフォルトの sql は自動接続プールを作りますが、max を明示しないと環境依存の既定値で動きます。本番では new Bun.SQL({ url, max: 10 }) のように明示設定するのが安全です。
よくある質問
Bun.serve + Bun.sql + Bun.redis)、CLI ツール、バッチ処理、モノレポのパッケージマネージャーは既に本番導入事例が多数あります。ただし sharp / canvas のような画像処理の重量級ライブラリ、特殊な N-API 依存を持つ SDK などを使う場合は、CI で動作確認してから慎重に移行してください。bun install の速度・HTTP スループット・ファイル IO がすべて大きく速いです。Meta 社内事例では初回ロード最大 12% 改善・一部操作 2.5 倍という数字が出ています。特に CI のパッケージインストール時間は 30〜70% 削減できるケースが多く、開発者体験(DX)の改善は即座に感じられます。tsc --noEmit や tsgo を CI で別タスクとして実行してください。React 19 以降の型更新については React 19 完全ガイド もご参考に。Bun.sql のタグ付きテンプレート、ORM の型推論とリレーションを使い込むなら Drizzle / Prisma、という住み分けが 2026 年の主流です。Drizzle は Bun.sql をドライバとして使える設計になってきており、型安全 ORM+ネイティブ高速ドライバの組合せが現実解です。ORM 全般の設計は Claude Code × データベース開発完全ガイド にまとめてあります。Bun.redis 推奨です。インストール不要・ネイティブ速度・プール管理組込み、と三拍子揃っています。既存で ioredis を使っているプロジェクトは、Sentinel / Cluster の高度機能を使っていないなら移行を検討してよいタイミングです。bun.lock は JSONC 形式で人間にも読めるため、PR レビューで依存バージョンの変化を追いやすい副次効果もあります。CI では bun install --frozen-lockfile を指定し、ロックファイルが変更されたらビルド失敗にすると、予期せぬ依存変更を防げます。まとめ
- Bun 1.3 が 2026 年の本命: Node.js 互換 90%+ /
bun.lock/Bun.sql/Bun.redis/Bun.s3/Bun.$/ Package Catalogs が揃い、本番投入の障壁が事実上消えた - 四位一体: Runtime(node 置換)・Package Manager(npm 置換)・Bundler(esbuild 置換)・Test Runner(Jest 置換)を 1 バイナリで提供。CI 時間を劇的に削減できる
- ネイティブ API(Bun.sql / Bun.redis / Bun.s3)で外部ライブラリ依存を減らし、性能と保守性を両取り
- Bun.$ でクロスプラットフォームのシェル。Windows / macOS / Linux を問わず同じ記法で書ける
- Single-file executableで Node.js を入れていないサーバーにもデプロイ可能。Docker イメージのサイズも激減
- 移行は段階的に: ① CI 並走 → ② スクリプト置換 → ③ bun test 移行 → ④ 本番 Runtime → ⑤ ネイティブ API 置換、の順が実害最小
- N-API 依存と大規模 Next.js 案件は慎重に。テストと計測で裏を取ってから判断する
React 19 / Supabase / Hono との組合せは相性抜群です。React 19 完全ガイド、TypeScript × Hono 完全ガイド、Claude Code × Supabase フルスタック開発完全ガイド、Claude Code × データベース開発完全ガイド、Claude Code × Next.js フルスタック開発完全ガイド もあわせて、Bun を核に据えた 2026 年型 TS フルスタック環境を組み上げてください。
