Bun で Hello API:超軽量 HTTP サーバを 5 分で公開する
Web API を構築したいけれど、Node.js は起動が遅い、Docker は重い……そんな悩みを抱えたことはありませんか? Bun は次世代の JavaScript ランタイムとして、圧倒的な速度と開発体験を提供してくれます。 この記事では、Bun を使って最小限の HTTP サーバを構築し、5 分で動かす手順をご紹介しますね。
背景
Node.js と新世代ランタイムの登場
これまで JavaScript のサーバサイド開発といえば Node.js が主流でした。 しかし、近年では Deno や Bun といった新しいランタイムが登場し、パフォーマンスや開発体験の向上が注目されています。
Bun は 2022 年に登場した比較的新しいランタイムですが、以下の特徴により急速に注目を集めているんです。
| # | 項目 | Node.js | Bun |
|---|---|---|---|
| 1 | 起動速度 | 標準 | 最大 4 倍高速 |
| 2 | パッケージマネージャ | npm/yarn 必要 | 組み込み |
| 3 | TypeScript サポート | トランスパイラ必要 | ネイティブサポート |
| 4 | テストランナー | Jest 等が必要 | 組み込み |
| 5 | バンドラー | Webpack 等が必要 | 組み込み |
Bun のアーキテクチャ
Bun の高速性を支える仕組みを図で見てみましょう。
mermaidflowchart TB
dev["開発者"] -->|コード記述| bunCore["Bun Core<br/>(Zig 言語実装)"]
bunCore -->|実行| jsEngine["JavaScriptCore<br/>(Safari のエンジン)"]
bunCore -->|統合| pkgMgr["パッケージマネージャ"]
bunCore -->|統合| bundler["バンドラー"]
bunCore -->|統合| testRunner["テストランナー"]
jsEngine -->|高速実行| app["アプリケーション"]
pkgMgr -->|依存管理| app
bundler -->|最適化| app
Bun は Zig 言語で実装されており、JavaScript エンジンには Safari で使われている JavaScriptCore を採用しています。 これにより、従来の V8 エンジンよりも起動が速く、メモリ効率も優れているのです。
課題
従来の HTTP サーバ構築の問題点
Node.js で HTTP サーバを構築する際には、いくつかの課題がありました。
1. セットアップの複雑さ
Node.js で API サーバを構築する場合、以下のような手順が必要でしたね。
mermaidflowchart LR
start["プロジェクト作成"] --> install1["Express インストール"]
install1 --> install2["TypeScript インストール"]
install2 --> config1["tsconfig.json 設定"]
config1 --> config2["nodemon 設定"]
config2 --> coding["コーディング開始"]
この一連の流れは、初心者にとってハードルが高く、単純な API を作るだけでも多くの設定が必要でした。
2. パフォーマンスの課題
Node.js の起動時間やリクエスト処理速度は、大規模なアプリケーションでは課題となることがあります。
| # | 指標 | Node.js + Express | Bun | 改善率 |
|---|---|---|---|---|
| 1 | 起動時間 | 約 200ms | 約 50ms | 4 倍高速 |
| 2 | Hello World レスポンス | 約 5ms | 約 0.5ms | 10 倍高速 |
| 3 | メモリ使用量 | 約 30MB | 約 10MB | 3 分の 1 |
3. 開発体験の問題
TypeScript を使う場合、型チェック、トランスパイル、ホットリロードなど、複数のツールを組み合わせる必要がありましたね。 これらの設定は開発速度を低下させる要因となっていました。
解決策
Bun による統合的アプローチ
Bun はこれらの課題を、オールインワンのツールチェーンで解決します。
mermaidflowchart TB
subgraph traditional["従来のアプローチ"]
node["Node.js"]
npm["npm/yarn"]
ts["TypeScript"]
bundler1["Webpack/Vite"]
test1["Jest"]
end
subgraph bunApproach["Bun のアプローチ"]
bunAll["Bun<br/>(すべて統合)"]
end
traditional -->|複雑| slow["遅い起動"]
bunApproach -->|シンプル| fast["高速起動"]
Bun を使うことで、以下のメリットが得られます。
メリット 1:ゼロコンフィグで TypeScript が動く
tsconfig.json の設定なしに、TypeScript ファイルをそのまま実行できます。
トランスパイルも内部で自動的に行われるため、余計な設定ファイルが不要なんですね。
メリット 2:標準 API で HTTP サーバを構築
Bun は Bun.serve() という組み込み API を提供しています。
Express のような外部ライブラリを使わずに、高速な HTTP サーバを構築できるんです。
メリット 3:高速なパッケージインストール
npm や yarn と比較して、最大 25 倍高速にパッケージをインストールできます。 これにより、CI/CD パイプラインの時間短縮にも貢献しますね。
具体例
それでは、実際に Bun で HTTP サーバを構築してみましょう。 5 分で完成する手順を、ステップバイステップで解説していきます。
ステップ 1:Bun のインストール
まずは Bun をインストールします。 macOS または Linux では、以下のコマンド一つで完了します。
bashcurl -fsSL https://bun.sh/install | bash
Windows の場合は WSL2 を使うか、公式サイトから Windows 用のインストーラをダウンロードしてくださいね。
インストールが完了したら、バージョンを確認してみましょう。
bashbun --version
これで 1.0.0 以上のバージョンが表示されれば成功です。
ステップ 2:プロジェクトの初期化
新しいディレクトリを作成し、Bun プロジェクトを初期化します。
bashmkdir hello-bun-api
cd hello-bun-api
次に、Bun のプロジェクト初期化コマンドを実行しましょう。
bashbun init
対話形式でいくつか質問されますが、すべてデフォルト(Enter キー)で問題ありません。
これにより、package.json と tsconfig.json が自動生成されます。
ステップ 3:最小限の HTTP サーバを作成
それでは、実際に HTTP サーバのコードを書いていきましょう。
index.ts ファイルを作成します。
サーバの基本構造
まず、Bun の serve 関数をインポートして、基本的なサーバ構造を作ります。
typescript// Bun の組み込み API をインポート
import { serve } from 'bun';
このインポート文だけで、HTTP サーバに必要な機能がすべて使えるようになります。 Express のような外部ライブラリは不要なんですね。
サーバ設定とハンドラの実装
次に、サーバの設定とリクエストハンドラを実装します。
typescript// HTTP サーバを起動
const server = serve({
// サーバのポート番号を指定
port: 3000,
// リクエストハンドラ関数
fetch(request) {
// リクエスト URL を解析
const url = new URL(request.url);
// パスに応じてレスポンスを返す
if (url.pathname === '/') {
return new Response('Hello, Bun API!');
}
// その他のパスは 404 を返す
return new Response('Not Found', { status: 404 });
},
});
fetch 関数がすべての HTTP リクエストを処理します。
Request オブジェクトから URL を取得し、パスに応じたレスポンスを返していますね。
サーバ起動メッセージの表示
最後に、サーバが正常に起動したことを確認するためのメッセージを表示します。
typescript// コンソールに起動メッセージを表示
console.log(
`🚀 Server running at http://localhost:${server.port}`
);
これで、サーバが起動したポート番号を確認できます。
ステップ 4:サーバの起動
作成したサーバを起動してみましょう。 Bun では非常にシンプルなコマンドで実行できます。
bashbun run index.ts
コンソールに以下のようなメッセージが表示されれば成功です。
arduino🚀 Server running at http://localhost:3000
Node.js のように ts-node や nodemon といったツールは不要です。
TypeScript ファイルをそのまま実行できるのが Bun の魅力ですね。
ステップ 5:動作確認
別のターミナルを開いて、API にアクセスしてみましょう。
bashcurl http://localhost:3000
以下のレスポンスが返ってくれば、API サーバが正常に動作しています。
Hello, Bun API!
ブラウザで http://localhost:3000 にアクセスしても、同じメッセージが表示されますよ。
発展:JSON API の実装
より実用的な API にするため、JSON レスポンスを返す例も見てみましょう。
API エンドポイントの拡張
index.ts を編集して、複数のエンドポイントを追加します。
typescriptconst server = serve({
port: 3000,
fetch(request) {
const url = new URL(request.url);
// ルートパス:テキストレスポンス
if (url.pathname === '/') {
return new Response('Hello, Bun API!');
}
// /api/status:JSON レスポンス
if (url.pathname === '/api/status') {
const data = {
status: 'ok',
timestamp: new Date().toISOString(),
message: 'API is running',
};
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
});
}
// その他:404 エラー
return new Response('Not Found', { status: 404 });
},
});
この例では、/api/status にアクセスすると JSON 形式のステータス情報が返ってきます。
JSON API の動作確認
新しいエンドポイントにアクセスしてみましょう。
bashcurl http://localhost:3000/api/status
以下のような JSON レスポンスが返ってきますね。
json{
"status": "ok",
"timestamp": "2025-11-16T12:34:56.789Z",
"message": "API is running"
}
リクエスト処理のフロー図解
これまで実装した API サーバの処理フローを図で整理してみましょう。
mermaidflowchart TD
client["クライアント"] -->|HTTP リクエスト| server["Bun HTTP サーバ"]
server -->|URL 解析| router["ルーティング判定"]
router -->|パス: /| rootHandler["テキストレスポンス<br/>Hello, Bun API!"]
router -->|パス: /api/status| apiHandler["JSON レスポンス<br/>ステータス情報"]
router -->|その他| notFound["404 Not Found"]
rootHandler --> response["Response 生成"]
apiHandler --> response
notFound --> response
response -->|HTTP レスポンス| client
図で理解できる要点:
- すべてのリクエストは
fetch関数で受け取られます - URL パスに応じて適切なハンドラが実行されます
- 各ハンドラは
Responseオブジェクトを生成して返します
パフォーマンス測定
実際に Bun の速度を体感してみましょう。 Apache Bench を使った簡単な負荷テストを行います。
bash# 1000 リクエスト、同時接続 100 で負荷テスト
ab -n 1000 -c 100 http://localhost:3000/
結果の一例を表で整理してみます。
| # | 指標 | 結果 |
|---|---|---|
| 1 | 秒間リクエスト数 | 約 50,000 req/sec |
| 2 | 平均レスポンスタイム | 約 0.2ms |
| 3 | メモリ使用量 | 約 12MB |
この数値は Node.js + Express と比較して、約 10 倍の性能を示しています。 軽量な API サーバには最適な選択肢といえるでしょう。
ホットリロードの有効化
開発効率をさらに向上させるため、ファイル変更時の自動再起動を設定しましょう。
Bun には --watch フラグが組み込まれています。
bashbun --watch run index.ts
これで、index.ts を編集して保存すると、自動的にサーバが再起動されます。
nodemon のような追加ツールは不要なんですね。
エラーハンドリングの追加
実用的な API にするため、エラー処理も追加してみましょう。
typescriptconst server = serve({
port: 3000,
fetch(request) {
try {
const url = new URL(request.url);
if (url.pathname === '/') {
return new Response('Hello, Bun API!');
}
if (url.pathname === '/api/status') {
const data = {
status: 'ok',
timestamp: new Date().toISOString(),
message: 'API is running',
};
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
});
}
return new Response('Not Found', { status: 404 });
} catch (error) {
// エラー発生時は 500 エラーを返す
console.error('Server error:', error);
return new Response('Internal Server Error', {
status: 500,
});
}
},
});
try-catch ブロックで例外をキャッチし、適切なエラーレスポンスを返すことで、サーバの安定性が向上します。
環境変数の活用
ポート番号をハードコーディングせず、環境変数から読み取るように改善しましょう。
typescript// 環境変数からポート番号を取得(デフォルトは 3000)
const port = Number(process.env.PORT) || 3000;
const server = serve({
port,
fetch(request) {
// 前述のハンドラと同じ
// ...
},
});
console.log(
`🚀 Server running at http://localhost:${server.port}`
);
これで、起動時に異なるポートを指定できます。
bashPORT=8080 bun run index.ts
Docker での実行(オプション)
本番環境でのデプロイを見据えて、Docker コンテナ化も見てみましょう。
Dockerfile の作成
プロジェクトルートに Dockerfile を作成します。
dockerfile# Bun の公式イメージを使用
FROM oven/bun:1
# 作業ディレクトリを設定
WORKDIR /app
# package.json をコピー
COPY package.json .
# 依存関係をインストール
RUN bun install
# ソースコードをコピー
COPY . .
# ポート 3000 を公開
EXPOSE 3000
# アプリケーションを起動
CMD ["bun", "run", "index.ts"]
Bun の公式 Docker イメージを使用することで、環境構築が非常にシンプルになりますね。
Docker イメージのビルド
Dockerfile ができたら、イメージをビルドします。
bashdocker build -t hello-bun-api .
コンテナの起動
ビルドしたイメージからコンテナを起動しましょう。
bashdocker run -p 3000:3000 hello-bun-api
これで、Docker コンテナ内で Bun API サーバが動作します。
完成形のディレクトリ構造
最終的なプロジェクト構造を整理してみましょう。
bashhello-bun-api/
├── index.ts # メインのサーバファイル
├── package.json # プロジェクト設定
├── tsconfig.json # TypeScript 設定
├── Dockerfile # Docker 設定(オプション)
└── README.md # プロジェクト説明(オプション)
非常にシンプルな構造で、複雑な設定ファイルは最小限に抑えられています。
まとめ
この記事では、Bun を使って HTTP サーバを 5 分で構築する方法をご紹介しました。 重要なポイントを振り返ってみましょう。
Bun の主な利点
- 高速起動:Node.js の約 4 倍の起動速度
- シンプルな開発体験:TypeScript をそのまま実行可能
- オールインワン:パッケージマネージャ、バンドラ、テストランナーが統合
- 組み込み HTTP サーバ:外部ライブラリ不要で軽量な API を構築
開発のステップ
- Bun のインストール(1 コマンド)
- プロジェクト初期化(
bun init) index.tsでサーバコードを記述bun run index.tsで起動- JSON API やエラーハンドリングを追加
こんな場面で活躍します
- プロトタイプ開発や検証用の API サーバ
- マイクロサービスの軽量なエンドポイント
- サーバーレス環境での高速な関数実行
- 開発環境での高速なホットリロード
Bun はまだ比較的新しいランタイムですが、その性能と開発体験の良さから、今後ますます注目されることでしょう。 まずは小さな API サーバから試してみて、その速度を体感してみてくださいね。
関連リンク
articleBun で Hello API:超軽量 HTTP サーバを 5 分で公開する
articleBun でクリーンアーキテクチャ:ドメイン分離・DI・テスト容易性の設計指針
articleNode.js と Deno と Bun を実測比較:コールドスタート/IO/HTTP/互換性レポート
articleBun コマンド チートシート:bun install/run/x/test/build 一括早見表
articleBun のインストール完全ガイド:macOS/Linux/Windows(WSL)対応の最短手順
articleBun とは?Node.js・Deno と何が違うのかを 3 分で理解【2025 年最新版】
articleSolidJS のアニメーション比較:Motion One vs Popmotion vs CSS Transitions
articleClaude Code セットアップ最短ルート:macOS での導入から初回実行まで
articleShell Script でファイル操作を極める:find・rsync・圧縮/展開の実践レシピ
articleRuby で業務自動化:スプレッドシート連携・メール配信・定期バッチの実例
articleBun で Hello API:超軽量 HTTP サーバを 5 分で公開する
articleRedis Pub/Sub vs Redis Streams:配信保証とスケーラビリティ比較
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来