BEMAロゴ

エンジニアの
成長を支援する
技術メディア

TypeScriptエンジニア必見!超軽量Webフレームワーク『Hono』入門:API開発からミドルウェア活用まで

はじめに

こんにちは、株式会社メンバーズの秋田です。

Node.js環境のバックエンド開発で「もっと手軽に書きたい」「より高速に起動・処理させたい」と思ったことはないでしょうか?
私自身、小規模なAPIを実装するために、フレームワーク特有の複雑なディレクトリ構成や定型的なコード記述に悩まされることがありました。リクエストを受け取ってレスポンスを返すというシンプルなAPIを実装するために、いくつものファイルを編集しなければならないことに、もどかしさを感じる場面も少なくありませんでした。

機能豊富なNestJSや成熟したExpressも有力な選択肢ですが、サーバーレス環境(AWS LambdaやCloudflare Workersなど)では、起動速度やバイナリサイズ、そして何より「開発体験の軽快さ」が重要な指標となります。

そこで本記事では、TypeScriptとの親和性が極めて高く、サーバーレス環境に最適な「Hono」の基本から、実践的なルーティング、ミドルウェアの実装方法までを解説します。

Honoとは?

Honoは元々はCloudflare Workers向けに作られたものですが、Node.jsでも動きます

Web API開発に必要な機能は一通り揃っており、NestJSなどよりも軽量なのでサーバーレスな環境(Lambda、 Cloudflare Workersなど)でもパフォーマンスがよく動作します。

この記事では、次のようなことを説明します。

  • Hello World!:Honoプロジェクトを作成して、GETリクエストを送信してレスポンスを取得する

  • ルーティング:APIのパスを追加する

  • コンテキスト:リクエスト、レスポンス、ヘッダーを操作する

  • ミドルウェア:APIの処理の前後で共通のロジックを実行する(ログ出力)

前提条件

  • Node.js:ver.24

  • Hono:ver.4.12.12

Hello World!

Honoプロジェクトを作成します。
npm createコマンドで、Honoを用いたバックエンドAPIのテンプレートを素早く構築できます。

# "my-app"ディレクトリを作成して、Honoプロジェクトを作成
npm create hono@latest my-app

# Node.js用のテンプレートを選択
? Which template do you want to use?
  lambda-edge
  netlify
  nextjs
❯ nodejs
  vercel
  cloudflare-pages
  x-basic

# 依存関係をインストール
? Do you want to install project dependencies? (Y/n) # Yを入力

# パッケージマネージャを選択
? Which package manager do you want to use? (Use arrow keys)
❯ npm

自動生成されたコードを確認します。

src/index.tsでは次のように、ルート(“/”)にGETでリクエストすると Hello Hono! というレスポンスを返すコードが実装されています。

app.get("/", (c) => {
  return c.text("Hello Hono!");
});

初期状態で動作することを確認するため、開発サーバーを起動します。

$ npm run dev
Server is running on http://localhost:3000

表示されたURLへアクセスすると、レスポンスが表示されます。

$ curl http://localhost:3000
Hello Hono!

ルーティング

ルーティングの定義を追加します。
確認用にルーティングから呼び出される実装を書いておきます。

// src/api/books.ts
// サンプルのAPI

import { Hono } from "hono";
const app = new Hono();

app.get('/',  (c) => {
    return c.text('books');
})

export default app;

これから作成するファイルを含めて、ディレクトリ構成は以下のようになります。

src
├── index.ts :APIのエントリポイントで、Honoインスタンスの生成とサーバーを設定する
├── api
│   └── books.ts :APIロジックやハンドラを実装する
└── routes.ts :ルーティングを定義し、各エンドポイントのパスと実際の処理を紐付ける

実際の開発では多くのルーティングを定義すると思うので、次のように別ファイルに切り出して作成します。

// src/routes.ts
// ルーティング定義のみを切り出したファイル

import { Hono } from "hono";
import books from "./api/books.js";

const router = new Hono();

router.route('/books', books);  // ルーティング

export default router;

エントリポイントでは次のようにルーティング定義を参照します。

// src/index.ts
import { Hono } from 'hono'
import routes from "./routes.js";

const app = new Hono()

app.route('/', routes)

export default app

追加したルーティング(/books)にアクセスすると、確認用のAPIが呼び出され次のように表示されます。

$ curl http://localhost:3000/books
books

コンテキスト

Honoではリクエスト、レスポンス、ヘッダーなどを操作できるコンテキストオブジェクトというものが用意されています。APIハンドラの第1引数にセットされており、リクエスト情報の取得からレスポンスの返却まで便利に利用できます。

  • c.req.param():パスパラメータの取得

  • c.req.query():クエリパラメータの取得

  • c.text():テキストレスポンスの返却

  • c.json():JSONレスポンスの返却

TypeScriptにより型補完されるため、以下のように c.req. と入力するだけで利用可能なメソッドが表示されます。

ミドルウェア

Honoではミドルウェアとしてリクエストを受信した時、レスポンスを返す時に共通の処理を実行することができます。
ここでは、リクエストごとにIDを割り当て、処理全体に要した時間を表示させてみます。

// src/index.ts
import { requestId } from 'hono/request-id' // ID生成用

// 各リクエストに一意のIDを割り振る
app.use('*', requestId())

リクエスト処理開始、完了時に出力

APIリクエストの処理開始前、処理完了後にログを出力するミドルウェアを次のように作成します。

// src/libs/logger-middleware.ts
import type { MiddlewareHandler } from 'hono'

export const structuredLogger = (): MiddlewareHandler => {
  return async (c, next) => {
    const start = Date.now()

    // リクエスト処理開始時のログ
    const startlogEntry = {
      time: new Date().toISOString(),
      requestId: c.get('requestId'),
      method: c.req.method,
      path: c.req.path
    }
    console.log(JSON.stringify(startlogEntry))

    // 次の処理を実行
    await next()

    // リクエスト処理完了時のログ
    const ms = Date.now() - start
    const logEntry = {
      time: new Date().toISOString(),
      requestId: c.get('requestId'),
      method: c.req.method,
      path: c.req.path,
      status: c.res.status,
      duration: `${ms}ms`,
    }

    console.log(JSON.stringify(logEntry))
  }
}

src/index.tsでは次のように書いて、どのAPIへアクセスしても上記のミドルウェアが実行されるようにします。

// src/index.ts
import { structuredLogger } from './libs/logger-middleware.js';

app.use('*', structuredLogger());

実際に何らかのAPIへアクセスすると、次のようにログが表示されます。

{"time":"2026-04-28T02:23:06.799Z","method":"GET","path":"/"}
{"time":"2026-04-28T02:23:06.803Z","requestId":"1e17347c-7d01-463e-b761-540249a9e693","method":"GET","path":"/","status":200,"duration":"4ms"}

まとめ

この記事ではWebフレームワークHonoの入門として、APIやルーティングの実装、コンテキストの説明、ミドルウェアの動作について解説しました。

実際にHonoを使ってみて強く感じたのは、環境構築からAPI実装、サーバー起動までを素早く実行でき、フレームワークの定型的なコードの記述に追われることが少なくなった点です。本来書きたかったドメインロジックを即座に書き始められる快感がありました。

「小規模なAPIを手軽に作りたい」「サーバーレス環境で最高のパフォーマンスを出したい」という方は、ぜひ一度Honoを触ってみてください。一度この開発体験を味わうと、もう以前の重厚な環境には戻れなくなるかもしれません。

この記事が役に立ったと思ったら、
ぜひ「いいね」とシェアをお願いします!

リンクをコピーXでシェアするfacebookでシェアする

この記事を書いた人

秋田 大介
秋田 大介
自社サービス開発企業にてシステム開発経験を積み、2023年にメンバーズに中途入社。Windowsソフト開発からWeb系にキャリアチェンジ。現在は、バックエンドを主軸にしながらも、フロントエンドも対応できるエンジニアとして業務している。
詳しく見る
ページトップへ戻る