ElysiaJSとBunで「超速」REST APIを構築:AからZまでのType Safety

Development tutorial - IT technology blog
Development tutorial - IT technology blog

なぜBunとElysiaJSが開発者コミュニティで話題なのか?

Node.jsでのtsconfig.jsonの設定やパッケージインストールの遅さに疲れていませんか?Bun + ElysiaJSの組み合わせは、非常に強力な代替手段です。npm installのたびに首を長くして待つ必要はもうありません。

私は約6ヶ月前から、実際のマイクロサービスにBunを導入し始めました。最初の印象を一言で言えば、「速い」に尽きます。Bunは単なるランタイムではなく、パッケージマネージャー、テストランナー、バンドラーを内蔵しています。一方、ElysiaJSはこのパワーを最大限に引き出すために設計されており、「最高速度」と「絶対的なType Safety」という哲学を持っています。

APIシステムをExpressからElysiaにリファクタリングしたところ、ボイラープレートコードが40%近く削減されました。特に、フロントエンド側の「undefined is not a function」エラーは、高度な型同期メカニズムのおかげでほぼ解消されました。

Bunランタイムの核心的なパワー

Node.jsのようにV8を使用する代わりに、BunはSafariブラウザの背後にあるJavaScriptCore (JSC)を採用しています。JSCには、起動が速く、メモリ管理が非常に厳格であるという利点があります。

大きな利点は、Bunが.tsファイルを直接実行できることです。bun run index.tsと入力するだけで完了です。以前のようにBabelやesbuildの複雑な設定に悩まされることはありません。

実践:5分でREST APIを構築する

まず、ターミナルからBunをインストールします:

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

次に、コマンド一つでElysiaJSプロジェクトを初期化します:

bun create elysia my-api
cd my-api

最小限のサーバー構成

src/index.tsを開くと、Elysiaのコードスタイルが非常にモダンであることがわかります。Fastifyに似ていますが、より簡潔です:

import { Elysia, t } from 'elysia'

const app = new Elysia()
  .get('/', () => 'itfromzero.comからの挨拶です!')
  .post('/user', ({ body }) => body, {
    body: t.Object({
      name: t.String(),
      age: t.Number()
    })
  })
  .listen(3000)

console.log(`サーバーが起動しました: ${app.server?.hostname}:${app.server?.port}`);

ここでのポイントはオブジェクトt(TypeBox)です。これはガードマンのような役割を果たします。クライアントがnameフィールドを忘れた場合、Elysiaは自動的にリクエストをブロックし、即座に400エラーを返します。手動でバリデーションロジックを書く必要は一切ありません。

Swaggerによるドキュメントの自動化

ドキュメントのないAPI作成はフロントエンドチームにとって悪夢です。Elysiaなら、わずか数秒の設定でSwagger UIが手に入ります。

プラグインのインストール:

bun add @elysiajs/swagger

コードへの統合:

import { Elysia } from 'elysia'
import { swagger } from '@elysiajs/swagger'

new Elysia()
  .use(swagger())
  .get('/posts', () => [{ id: 1, title: 'IT From ZeroでBunを学ぶ' }])
  .listen(3000)

localhost:3000/swaggerにアクセスすると、プロフェッショナルなAPIテストインターフェースが表示され、手動でドキュメントを作成する時間を大幅に節約できます。

Eden Treatyの秘策:フロントとバックを隙間なく接続

これは私が最も気に入っている機能です。通常、バックエンドでデータ型が変更されると、フロントエンドの更新が間に合わず「壊れて」しまうことがよくあります。

Eden Treatyは、フロントエンドがバックエンドからすべての型を「継承」できるようにすることで、この問題を根本的に解決します。Shared Libsのようにインターフェースを手動でコピー&ペーストする必要はありません。

バックエンドプロジェクトでは、アプリの型をエクスポートするだけです:

export type App = typeof app;

フロントエンド(React/Next.js)側:

import { edenTreaty } from '@elysiajs/eden'
import type { App } from '../backend/src/index'

const client = edenTreaty<App>('http://localhost:3000')

// Intellisenseがエンドポイントとデータ型を正確に提案します
const { data } = await client.hello.get() 

100以上のエンドポイントを持つ実際のプロジェクトでは、変数名のリファクタリングが非常に安全になります。バックエンドでフィールド名を変更すると、IDEがフロントエンドのコード上で即座にエラーを表示します。これが、プロフェッショナルなエラー管理にも通ずるEnd-to-End Type Safetyの力です。

Bunを使用する際の実践的な経験

  • Bun SQLite: 小規模なアプリやキャッシュが必要な場合は、内蔵のSQLiteを使用しましょう。クエリ速度は従来のドライバーよりも大幅に高速です。
  • Context管理: ユーザーセッションの管理には、グローバル変数ではなく、Elysiaの.state().derive()を優先的に使用してコンテキストを管理してください。
  • テスト速度: bun testはJestよりも約10〜20倍高速です。これを活用してフィードバックループを短縮し、コードの自信を高めましょう。

Bunはまだ不安定ではないかと心配する人も多いでしょう。しかし、バージョン1.x以降、Bunは真に成熟し、本番環境への導入準備が整っています。古くて遅いツールに甘んじるのはもうやめましょう。

ElysiaJSとBunを体験することは、単にトレンドを追うことではありません。生産性を最適化し、APIの不整合などのプログラミングにおける初歩的なミスを排除するための方法です。今日、小さなプロジェクトを作成して、このコンボの滑らかさを実感してみてください!

Share: