【時代はHono🔥!?】今さらながらNext.js App RouterユーザがHonoを調べてみた

# 目次

1. [はじめに](https://qiita.com/john-Q/items/394ba6ffdba08580f1bc#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)
1. [想定読者](https://qiita.com/john-Q/items/394ba6ffdba08580f1bc#%E6%83%B3%E5%AE%9A%E8%AA%AD%E8%80%85)
1. [TL;DR](https://qiita.com/john-Q/items/394ba6ffdba08580f1bc#tldr)
1. [Honoとは](https://qiita.com/john-Q/items/394ba6ffdba08580f1bc#hono%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F)
1. [Trends](https://qiita.com/john-Q/items/394ba6ffdba08580f1bc#trends)
1. [Honoを使ってみた](https://qiita.com/john-Q/items/394ba6ffdba08580f1bc#hono%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F)
1. [Next.jsとの比較](https://qiita.com/john-Q/items/394ba6ffdba08580f1bc#nextjs%E3%81%A8%E3%81%AE%E6%AF%94%E8%BC%83)
1. [ユースケース](https://qiita.com/john-Q/items/394ba6ffdba08580f1bc#%E3%83%A6%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%82%B9)
1. [所感](https://qiita.com/john-Q/items/394ba6ffdba08580f1bc#%E6%89%80%E6%84%9F)
1. [まとめ](https://qiita.com/john-Q/items/394ba6ffdba08580f1bc#%E3%81%BE%E3%81%A8%E3%82%81)

# はじめに
こんにちは、「拳で」 と申します!
[NRI OpenStandia Advent Calendar 2024](https://qiita.com/advent-calendar/2024/nri-openstandia)の9日目は 

**<font color="#ff5c0a">【時代はHono🔥!?】今さらながらNext.js App RouterユーザがHonoを調べてみた</font>** 

というタイトルでお送りいたします!

最近Honoについての記事や情報をよく見かけるようになり、全く調べたり触ったりしたことがなかったのでこの機会に調べてみました。

Next.js App Routerを使って、3案件ほどこなしたことがあるのでNext.jsユーザ目線で調べて思ったことなども書きました。

# 想定読者

この記事は以下のような方を想定して書いています。

- Honoのこと、全然知らないけど概要を知りたい
- Honoの2024年時点での立ち位置を知りたい
- Honoを使っていて、複数エンドポイント(Grouping routes)・OpenAPI Docs対応・RPCモード対応したサンプルコードが見たい

# TL;DR

- Honoは**2024年に特に伸びてきている**
- Honoは**軽量・高速で開発体験が優れたフレームワークで、特にエッジやバックエンド開発に最適**
    - Expressの代替になる
- Honoの**開発者体験は良い**

[Honoを使ってみた](https://qiita.com/john-Q/items/394ba6ffdba08580f1bc#hono%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F)で紹介したコードは、以下リポジトリで公開しています💡

https://github.com/jonghyo/Hono-gym

- Next.jsと比較し、両者フルスタックフレームワークだが**Honoはバックエンド(API)開発や軽量・ポータビリティに強み**
    - 比較表

![hono-nextjs.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/f3ef3ba8-57e5-b1d1-f8d7-348994ab0322.jpeg)
- Hono・Next.jsで**両者補完する構成**も良い
- Expressの代替やエッジでのプロキシ用途、Next.jsとの併用などがユースケースとして向いてそう

# Honoとは

## Honoの概要

[![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=honojs&repo=hono)](https://github.com/honojs/hono)

HonoはJavaScriptのWebフレームワークです。

```typescript:Hono sample code for Node.js
import { serve } from '@hono/node-server'
import { Hono } from 'hono'

const app = new Hono()
app.get('/', (c) => c.text('Hello Node.js!'))

serve(app)
```

上記サンプルのように[Express](https://expressjs.com/)に似た書き味で、WebAPIの開発ができます。
※[v3.1.0](https://github.com/honojs/hono/releases/tag/v3.10.0)以降はJSXもサポートして、フルスタックフレームワークになったようです!

比較のため、Expessのサンプルコードも載せておきます。

```javascript:express sample code
const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})
```

Cloudflare内はもちろん、CyberAgent, Prismaなど様々な組織・団体で実利用されているようです。
以下は、Honoを利用していることを公表している組織・団体の情報です。

https://speakerdeck.com/yusukebe/hono-v4?slide=13

https://github.com/orgs/honojs/discussions/1510

:::note info
**コラム：Honoの成り立ち**
- Yusuke Wadaさんが開発される、日本発のフレームワークです
- 開発当初は、Cloudflare Workers(エッジ環境)に特化した「Webアプリを作るためのフレームワーク」をコンセプトに開発されています
- Hono[炎]は、Cloud**flare**のflare(炎)とかけたネーミングが由来
- 開発初期のYusuke Wadaさんの記事：[Hono[炎]っていうイケてる名前のフレームワークを作っている](https://zenn.dev/yusukebe/articles/0c7fed0949e6f7)
:::

## Honoの特徴

Honoは以下のような特徴があります。

- **爆速**：JavaScriptのWebフレームワーク内で<font color="#ff5c0a">最速</font>
    - [ベンチマーク](https://hono.dev/docs/concepts/benchmarks)
- **軽量**：Minify すれば <font color="#ff5c0a">14KB 以下</font> (Express は 572KB) [^1]
- **ルーター**：5種類のルーターを持ち、目的に応じて使い分けできます。特に[RegExpRouter](https://hono.dev/docs/concepts/routers#regexprouter)は<font color="#ff5c0a">JavaScript界隈で最速のルーター</font>です
    - Hono v4で登場した、HonoとViteを組み合わせたメタフレームワーク [HonoX](https://github.com/honojs/honox)ではFile-based Routingも提供されます
- **Web標準**：HonoはWeb <font color="#ff5c0a">標準のみを使用して実装</font>されています。 <font color="#ff5c0a">Web 標準 API をサポートするあらゆるランタイムで動作</font>
    - Cloudflare Workers, Fastly Compute, Deno, Bun, Vercel, Netlify, AWS Lambda , Lambda@Edge, Node.js などで動作
- **ミドルウェア & ヘルパー**：シンプル・軽量なコアに、豊富な[ミドルウェア](https://hono.dev/docs/guides/middleware#middleware)・[ヘルパー](https://hono.dev/docs/guides/helpers#helpers)を<font color="#ff5c0a">適宜組み込むことで機能追加可能</font>
- **開発体験**：TypeScriptによる型のサポートや、[RPCモード](https://hono.dev/docs/guides/rpc#rpc)による<font color="#ff5c0a">型安全なAPIクライアントの生成が簡単にできます</font>

開発体験を意識した機能が豊富なので好印象...!

# Trends

> Express is the new JQuery

という界隈で一時話題になったポストや

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Express is the new JQuery</p>&mdash; Ben Holmes (@BHolmesDev) <a href="https://twitter.com/BHolmesDev/status/1679907011918430221?ref_src=twsrc%5Etfw">July 14, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

**I Stopped Using Express.js: Because Bun and Hono 🔥**

と題して、Expressではなく、Honoを使いだしたという方も登場してきており

<iframe width="560" height="315" src="https://www.youtube.com/embed/uxMADW3CmN4?si=Gvbgg1LtfwZ9WXHf" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

Honoの台頭とともに、脱Expressする人も増えてきている？？気がしてます。

「拳で」の体感では <font color="#ff5c0a"> **2024年になってよくHonoの記事や事例を見聞きするようになった**</font>のですが、トレンドはどうなってるか調べてみました。

今回各ツールのトレンドを比較するため

- [GitHub Star History](https://qiita.com/john-Q/items/ef7c433a5f441ff89ffb#github-star-history)
- [npm trends](https://qiita.com/john-Q/items/ef7c433a5f441ff89ffb#npm-trends)
- [State of JavaScript](https://qiita.com/john-Q/items/ef7c433a5f441ff89ffb#state-of-javascript)
- [JavaScript OpenSource Award](https://osawards.com/javascript/2024)

の調査を行いました。

比較対象は以下です。

| プロダクト名                                                          | Stars                                                                                       |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| [Express](https://github.com/expressjs/express)                   | <a href="https://github.com/expressjs/express"><img alt="GitHub stars" src="https://img.shields.io/github/stars/expressjs/express?style=social"/></a> |
| [Fastify](https://github.com/fastify/fastify)                     | <a href="https://github.com/fastify/fastify"><img alt="GitHub stars" src="https://img.shields.io/github/stars/fastify/fastify?style=social"/></a>       |
| [Elysia](https://github.com/elysiajs/elysia)                      | <a href="https://github.com/elysiajs/elysia"><img alt="GitHub stars" src="https://img.shields.io/github/stars/elysiajs/elysia?style=social"/></a>       |
| [Next.js](https://github.com/vercel/next.js)                      | <a href="https://github.com/vercel/next.js"><img alt="GitHub stars" src="https://img.shields.io/github/stars/vercel/next.js?style=social"/></a>         |

## GitHub Star History

[GitHub Star History](https://star-history.com/)で各GitHubリポジトリのStar数推移をチェックしてみました。

![star-history-2024123.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/17c59ed2-5e7f-5fd3-7109-571157638b52.png)


引用：[GitHub Star History | Hono vs express vs fastify vs elysia vs Next.js](https://star-history.com/#honojs/hono&expressjs/express&fastify/fastify&elysiajs/elysia&vercel/next.js&Date)

2022年に登場したHonoはかなりの勢いでStar数を増やしてますね!
特に2024年の加速は目覚ましいものがあり、よくHonoの記事や事例を目にするのも納得がいきました。

## npm trends

つぎｎ[npm trends](https://npmtrends.com/)を比較しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/b16834a8-45e1-4e05-a3a4-2e84ac7334c7.png)

expressやNext.jsを比較対象に加えると他のプロダクトのグラフが潰れてしまったので除外しています。

やはり、2024年から特にダウンロード数が増えてますね :eyes: 

引用：[npm trends | elysia-vs-fastify-vs-hono](https://npmtrends.com/elysia-vs-fastify-vs-hono)

## State of JavaScript

[State of JavaScript 2023](https://2023.stateofjs.com/en-US/other-tools/#backend_frameworks)調査結果から回答者が普段使っているBack-end Frameworksのランキングでは全体12位という結果でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/946becf5-7f8e-1eca-96a4-94ad1f0eb5ed.png)

回答者の1%が使っているという状況でしたが

- 回答の選択肢にHonoがなかった
- 「その他」の自由入力欄にHonoを記入した人が一定数いた

というのも少し影響している気がします。

[State of JavaScript 2024](https://survey.devographics.com/ja-JP/survey/state-of-js/2024)のSurveyでは回答選択肢にHonoが追加されており、今年の躍進を見る限りランキングの大幅アップも期待できそうですね!

<img alt="State of JavaScript 2024" width="400px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/9c549e58-0ce8-aa97-8b36-027a038bf90d.png"/>

## JavaScript OpenSource Award

JavaScript OpenSource Award 2024のThe Most Exciting Use of Technology部門にノミネートされていました!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/6646c2da-5054-dbca-dae0-010329de2306.png)

惜しくも受賞とはならなかったようですが、Honoは2024年のJavaScript界隈で注目を集めたプロダクトの1つですね!

# Honoを使ってみた

前置きが長くなりましたが、早速Honoを使ってみましょう!

コードは以下リポジトリで公開しています💡

https://github.com/jonghyo/Hono-gym

複数のエンドポイントを定義した、[Grouping routes](https://hono.dev/examples/grouping-routes-rpc)構成の上で

- OpenAPI Docs対応
- RPCモード対応

しているサンプルになるので、よかったらぜひご覧ください :eyes:
※Grouping routesで上記2つに対応しているサンプルコードをあまり見つけきらなかったので、お役に立てれば幸いです..

## Geting Started

https://hono.dev/docs/getting-started/basic

を参考にプロジェクトを作成します。

```bash
npm create hono@latest my-app
```

このコマンドを打つと、インタラクティブなCLIでプロジェクトが作成できます。
便利!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/092e972f-9e4e-6dd7-f05f-8c67d32c8c9e.png)

どのランタイムで動作させるか、テンプレートを選択できます。

```typescript:server.ts
import { serve } from '@hono/node-server'
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => {
  return c.text('Hello Qiita AdventCalendar 2024!')
})
const port = 3000
console.log(`Server is running on http://localhost:${port}`)
serve({
  fetch: app.fetch,
  port
})
```

テンプレートから生成されたコードをそのまま実行して、用意されたエンドポイントにcurlしてみます。

```bash
curl -v localhost:3000
* Host localhost:3000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:3000...
* Connected to localhost (::1) port 3000
> GET / HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/8.7.1
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 200 OK
< content-type: text/plain; charset=UTF-8
< Content-Length: 31
< Date: Wed, 04 Dec 2024 14:53:25 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< 
* Connection #0 to host localhost left intact
Hello Qiita AdventCalendar2024!
```

returnに設定されたテキストが返ってきますね!
記述はExpressライクな印象

## RPCモード

次に個人的に、非常に注目しているPRCモードを試してみます。

https://hono.dev/docs/guides/rpc#rpc

### RPCモードとは

RPCモードとは以下のような機能です。

> - Web APIの仕様、特にインプット・アウトプットをサーバーとクライアント間で共有するためのもの
> - OpenAPIやgRPCを使ってやりたかったことを叶えるかもしれない
> - サーバーとクライアントをどちらもTypeScriptで書くことが大前提である
> - 同種のものにtRPCがあるが、Honoの場合、普通のREST APIを書くだけで使える
> - クライアントはfetchのラッパーであり、スタンダードなResponseオブジェクトを扱う
> - いわゆる「型安全」を提供するものであり、エディタの補完がバチバチに効く

引用：[見よ、これがHonoのRPCだ](https://zenn.dev/yusukebe/articles/a00721f8b3b92e)

ざっくりいうと

今までOpenAPI Specから[openapi-typescript](https://github.com/openapi-ts/openapi-typescript)とかを使って作っていた、<font color="#ff5c0a">型安全なAPI ClientをHonoでAPI書くだけで簡単に実現できる機能</font>です。

これがめっちゃ便利...!

### server

ひとまず、普通にAPIを作成します。

**メソッドチェーンで定義** すると、RPCモードが使えるようになります。
ついでに、zodによるpost valueのバリデーションチェックも加えます。

```typescript:server.ts
import { serve } from '@hono/node-server'
import { zValidator } from '@hono/zod-validator'
import { Hono } from 'hono'
import { z } from 'zod'

const app = new Hono()

const schema = z.object({
	name: z.string().min(1),
	country: z.string().min(1),
})

const routes = app
	.get('/', (c) => {
		console.table(c)
		return c.text('Hello Qiita AdventCalendar 2024!')
	})
	.get('/api/users', (c) => {
		return c.json({
			user: 'foo-users',
		})
	})
	.post('/api/users', zValidator('json', schema), (c) => {
		const { name, country } = c.req.valid('json')
		return c.json({
			message: `Hello, ${name}. Your country is ${country}.`,
		})
	})

const port = 3000
console.log(`Server is running on http://localhost:${port}`)

serve({
	fetch: app.fetch,
	port,
})

// routesの型を取り、exportしておく
export type AppType = typeof routes
export default app
```

curlでデータをpostしてみます。

```bash
❯ curl -X POST localhost:3000/api/users -H 'Content-Type: application/json' -d '{"name":"jong","country":"japan"}'

{"message":"Hello, jong. Your country is japan."}
```

postしたデータが正しく受信できてそうです!
次にあえてバリデーションチェックエラーを起こしてみます。

```bash
❯ curl -v -X POST localhost:3000/api/users -H 'Content-Type: application/json' -d '{"name":"jong"}'
Note: Unnecessary use of -X or --request, POST is already inferred.
* Host localhost:3000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:3000...
* Connected to localhost (::1) port 3000
> POST /api/users HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/8.7.1
> Accept: */*
> Content-Type: application/json
> Content-Length: 15
>
* upload completely sent off: 15 bytes
< HTTP/1.1 400 Bad Request
< content-type: application/json; charset=UTF-8
< Content-Length: 163
< Date: Wed, 04 Dec 2024 15:23:34 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
* Connection #0 to host localhost left intact
{"success":false,"error":{"issues":[{"code":"invalid_type","expected":"string","received":"undefined","path":["country"],"message":"Required"}],"name":"ZodError"}}
```

HTTPステータス 400のレスポンス定義はしてませんが、よしなにステータスコードやエラーメッセージをレスポンスしてくれて便利😍

zodのschemaで`min(1)`していすれば、requireに指定できますね。

### client

server側で生成したAPIの型を`hc`に与えることで、型安全なAPI Clientを生成できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/37c8c11c-2e6d-23dc-d488-366c8b594078.png)

しっかり、エディタの型補完の恩恵を受けることができます!!
これは簡単・便利ですね!

```typescript:client.mts
import { hc } from 'hono/client'
import type { AppType } from './server'

// TypeSafeなAPI Clientを生成
const client = hc<AppType>('http://localhost:3000/')

const res = await client.api.users.$post({
	json: {
		name: 'Qiita',
		country: 'japan',
	},
})

if (res.ok) {
	const data = await res.json()
	console.log(data)
}
```

```bash:実行結果
❯ npx tsx src/client.mts
{ message: 'Hello, Qiita. Your country is japan.' }
```

問題なく、使えます!
こんなサクサクとTypeSafeなAPI Clientが作れるのは素敵...

参考

https://zenn.dev/yusukebe/articles/a00721f8b3b92e

### Custom fetch method

`hc`で生成されるAPI Clientはfetchなので、必要に応じてAPI Clientをカスタマイズできます。
先程のコードにカスタムヘッダを追加してみます。

```typescript:client.mts
import { hc } from 'hono/client'
import type { AppType } from './server'

// TypeSafeなAPI Clientを生成
const client = hc<AppType>('http://localhost:3000/', {
	fetch: (input: RequestInfo | URL, requestInit?: RequestInit) => {
		const headers = new Headers(requestInit?.headers) // 既存のヘッダを保持
		headers.set('x-qiita-custom-header', 'qiita adventcalendar 2024') // カスタムヘッダを追加

		return fetch(input, {
			...requestInit,
			headers, // 更新されたヘッダをセット
		})
	},
})

const res = await client.api.users.$post({
	json: {
		name: 'Qiita',
		country: 'japan',
	},
})

if (res.ok) {
	const data = await res.json()
	console.log(data)
}
```

サーバ側でカスタムヘッダを受信できてます!

```bash
> dev
> tsx watch src/server.ts

Server is running on http://localhost:3000
{
  accept: '*/*',
  'accept-encoding': 'gzip, deflate',
  'accept-language': '*',
  connection: 'keep-alive',
  'content-length': '34',
  'content-type': 'application/json',
  host: 'localhost:3000',
  'sec-fetch-mode': 'cors',
  'user-agent': 'node',
  'x-qiita-custom-header': 'qiita adventcalendar 2024'  //custom header
}
```

https://hono.dev/docs/guides/rpc#custom-fetch-method

:::note warn
RPCモードの利用について
[tRPC vs ts-rest vs Hono RPC](https://leaves.chiba.dev/posts/267)
の記事にもあるとおり、モノレポや同一プロジェクトでない場合RPCモードを使うのは工夫が必要です。

※Honoを使ってAPIを構築するプロジェクトが別リポジトリの場合、package化してroutesの型を別リポジトリにimportしたりが必要
:::


## OpenAPI

HonoはOpenAPI形式でスキーマを定義することで、APIドキュメントの生成も簡単にできます。

こちらの記事が大変参考になりました :bow: 

https://zenn.dev/slowhand/articles/b7872e09b84e15

以下のようにOpenAPI形式でrouteを定義すると

```typescript:route.ts
import {
  ErrorSchema,
  UserGetResSchema,
  UserPostResSchema,
  UserReqSchema,
} from '@/schema/web/userSchema'
import { createRoute } from '@hono/zod-openapi'

export const userGetRoute = createRoute({
  method: 'get',
  path: '/users',
  responses: {
    200: {
      content: {
        'application/json': {
          schema: UserGetResSchema,
        },
      },
      description: 'Returns a sample user name.',
    },
  },
})

export const userPostRoute = createRoute({
  method: 'post',
  path: '/users',
  request: {
    body: {
      content: {
        'application/json': {
          schema: UserReqSchema,
        },
      },
    },
  },
  responses: {
    200: {
      content: {
        'application/json': {
          schema: UserPostResSchema,
        },
      },
      description: 'Returns a posted user name, country.',
    },
    400: {
      content: {
        'application/json': {
          schema: ErrorSchema,
        },
      },
      description: 'Bad Request',
    },
  },
})
```

```typescript:server.ts
import { webRouter } from '@/routes/web'
import { serve } from '@hono/node-server'
import { swaggerUI } from '@hono/swagger-ui'
import { OpenAPIHono } from '@hono/zod-openapi'
import { logger } from 'hono/logger'
import { prettyJSON } from 'hono/pretty-json'

const baseApp = new OpenAPIHono().basePath('/api')

baseApp.use('*', prettyJSON())
baseApp.use('*', logger())

// OpenAPIドキュメントの生成
baseApp
  .doc31('/doc', {
    openapi: '3.1.0',
    info: {
      title: 'API',
      version: '1.0.0',
    },
  })
  .get(
    '/ui',
    swaggerUI({
      url: '/api/doc',
    }),
  )

const app = baseApp.route('/web', webRouter)

const port = 3000
console.log(`Server is running on http://localhost:${port}`)

serve({
  fetch: app.fetch,
  port,
})

export type AppType = typeof app

```

簡単にSwagger UIのAPIドキュメントを生成できます!!
便利すぎる...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/d6887c5c-8aa5-e6de-ade3-e301cf6f2183.png)

もちろん、RPCモードも使えます。

# Next.jsとの比較	

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/b7f4675f-9b71-b806-d1fa-3feb5c581cbd.png)

HonoとNext.jsはどういった関係性なのか比較してみました。

## 成り立ち

Yusuke Wadaさんが以下のようにポストしてます。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">HonoでやりたいのはNext.jsがReactというフロントエンドの文脈から出てきたのに対して、我々はサーバーサイドからExpressの代替としてWeb Standardsを武器に攻めるというチャレンジである。</p>&mdash; Yusuke Wada (@yusukebe) <a href="https://twitter.com/yusukebe/status/1752686096264396970?ref_src=twsrc%5Etfw">January 31, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/c4972292-b511-7840-3300-fc11bdbc3486.png)
引用：[Hono v4](https://speakerdeck.com/yusukebe/hono-v4?slide=84)より

個人的に以下のような印象を受けます。

- Hono：Expressの代替や、エッジ環境でのAPI開発目的が出発点
    - バックエンド側の機能が充実。エッジ環境やマルチランタイム対応に強み。シンプルで軽量なフレームワーク
- Next.js：Reactのメタフレームワークとして、画面開発目的が出発点
    - フロントエンド側の機能が充実。バックエンドの機能も含め、様々な機能を有する重厚なフレームワーク

## HonoとNext.jsの機能比較

ざっくりですが、HonoとNext.jsの機能や特徴を比較してみました。
※誤りがあったら申し訳ございません :bow:

![hono-nextjs.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/f3ef3ba8-57e5-b1d1-f8d7-348994ab0322.jpeg)

こう並べてみると、Honoもフルスタックフレームワークに位置付けられますね。

- Honoは柔軟なミドルウェアを駆使したAPI開発に強み
- Next.jsは画面系の開発に強み

といった印象を受けます。
双方のフレームワークの出自のとおりですね。

## HonoとNext.jsの関係性

今のところ、両者がカチ合って直接の競合になるイメージは湧きません。

- API開発やエッジでの処理が主体のアプリケーション：Hono
- フロント系の開発が主体のアプリケーション：Next.js

という棲み分けです。

両者は補完関係にもあるので、美味しいとこ取りする構成は魅力的です。

参考

https://zenn.dev/chot/articles/e109287414eb8c

# ユースケース

「拳で」がHonoについて調べながら、このユースケースが向いてるなと個人的に感じたものを並べます。

## 1. Expressの代替

まず、ぱっと思い浮かんだのはこちらです。
既存のExpressプロジェクトのリプレースは大変だと思うので、新規案件でAPIをTypeScriptで書く場合は選択肢に入れても良さそう。

## 2. Lambdalith

AWS Lambda・Lambda@Edgeを使うケースでLambdalith構成を選択する場合、マルチランタイム対応しているHonoは選択肢に入ると思います。

AWS管理ランタイムを気にしなくて良くなる恩恵はあるかなと。

参考

https://zenn.dev/watany/articles/183d40f8e31a45

## 3. エッジでのプロキシ

Yusuke Wadaさんの資料で紹介されていますが、エッジ上で

- レスポンスヘッダーのハンドリング
- CORS対応
- キャッシュ

など様々な用途で、Honoは活躍すると思います。

詳細は、資料参照

https://speakerdeck.com/yusukebe/shi-jian-etuziyusukesu?slide=62

## 4. Next.jsのRoute Handler内での利用

Next.jsでRoute Handlerを使う構成を考えている場合、<font color="#ff5c0a">Route HandlerでHonoを採用する</font> のはかなりアリな構成だなと思いました。

<font color="#ff5c0a">RPCモードで型安全なAPI Clientを生成し、Next.jsの画面側のコードでそれを使う</font> とアプリケーションの品質を高めることができそうです。

Honoを採用しておくと
<font color="#ff5c0a">Route Handler内でCPU boundな処理によって、プロセスがハングしてNext.jsの画面応答もしなくなる</font> ような性能問題に直面したとき、<font color="#ff5c0a">Route Handler(= API)部分だけ後々分離</font>したりできます。
※そもそもNodeで、CPU boundな処理するなって話はありますが...😅

Node.jsでCPU boundな処理をすると...の件は、[PLAIDがNode.jsを採用し、5年間で12万行書いてわかったこと](https://tech.plaid.co.jp/plaid_loves_nodejs)が参考になります。

参考

https://zenn.dev/oliver/articles/hono-advent-calendar-2024

## 5. BFF

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671490/42c8c824-3e6d-420e-03d3-50ff19df91fe.png)
引用：[流行りのBFFアーキテクチャとは？｜Offers Tech Blog](https://zenn.dev/overflow_offers/articles/20220418-what-is-bff-architecture)より

BFFは一般的に広く公開するのではなく、特定のアプリケーションのために構築するので個人的にOpenAPI specをわざわざ書くのはだるいなーと思ってました。

HonoならRPCモードで活用ができて、簡単にOpenAPIドキュメントが作れるので心理的ハードルは低いと感じました。

## 6. エッジでAPI + 簡単な画面を返したいとき

JSX対応やHonoXでファイルベースルーティングにも対応し、フルスタックWebアプリケーションフレームワークとしての活用もできそうです。

エッジ側でも簡単な処理や画面のレスポンスなら行けるので、軽量フレームワークとして...

# 所感

Honoを調査してみて、以下を感じました。

- **シンプル・軽量で開発者体験も非常に良い**
    - 特に、OpenAPI・RPCモードは非常に良い
- **マルチランタイム対応しており、ポータビリティ性が高いのはありがたい**
    - Next.jsのRoute Handlerに組み込んだりとか使える範囲が広い
- **公式ドキュメントがよりリッチになると嬉しい**
    - middlewareのオプションなどは網羅的に書かれてるわけではない
    - middlewareのリポジトリ側では、情報が提供されているので大きな問題ではないが
        - 例：[@hono/zod-openapi](https://github.com/honojs/middleware/tree/main/packages/zod-openapi)
- RPCモードは便利だが、モノレポ・同一プロジェクトでないと使いづらいので大規模プロジェクトでどう活用するかは工夫が必要??

実案件で使ってみたいと思いました。
ひとまず、趣味プロジェクトやハッカソンとかで使ってみるかな..🤩

# まとめ

Honoについて色々と調査した内容をまとめさせていただきました。
シンプルながら奥深く、様々なユースケースが挙げられるのでこれから更に注目していきたいと思います :eyes: 

# 参考資料

- [Hono公式ドキュメント](https://hono.dev/docs/)
- [Hono[炎]っていうイケてる名前のフレームワークを作っている](https://zenn.dev/yusukebe/articles/0c7fed0949e6f7)
- [Honoの今の状況](https://yusukebe.com/posts/2023/current-status-of-hono/)
- [Hono v4](https://speakerdeck.com/yusukebe/hono-v4)
- [Honoの来た道とこれから 文字版！](https://zenn.dev/yusukebe/articles/1abed4d99e8893)
- [Honoの概要とその特徴: Web標準に従った軽量高速フレームワーク](https://www.issoh.co.jp/column/details/3001/)
- [覚書：Honoとは？次世代フレームワークが注目される理由～その魅力と可能性～](https://note.com/yukkie1114/n/nf61d8d32641f)
- [Honoを使い倒したい2024](https://zenn.dev/aishift/articles/a3dc8dcaac6bfa)

[^1]: https://hono.dev/docs/#lightweight より