Hono CLI 爆誕
これまでHonoは数々の新しいことを提供してきました。正規表現を活かしたルーター、サーバーサイドの軽量JSX、TypeScriptの型によるRPC、Web Standardを使ったマルチランタイム対応などなど。アイデアと実装力で世界と戦って来たわけです。
本日私達が紹介するのは「Hono CLI」です。
Hono CLIは全く新しいコンセプトのコマンドラインインターフェースです。
-
create-*
ではありません - ただの開発用(
dev
&build
&deploy
)のコマンドではありません - Viteのラッパーではありません
人間とAIのためのCLIです。インストールすると
hono --help
のようにhono
コマンドを使うことができます。5つのサブコマンドがあります。
hono docs
hono search
hono request
hono serve
hono optimize
では一つ一つを見ていきましょう。
hono docs
最初はhono docs
です。このように実行します。
hono docs [path]
path
にはHonoのWebサイト(https://hono.dev)のパスを指定します。例えば「Routing」のページを指定したければこのようにします。
hono docs /docs/api/routing
これでドキュメントを見ることができるわけです。
でもあなたは思ったでしょう。「これだけですか?」と。そうこれだけです。しかしポイントは「標準出力にMarkdownが出力される」ことです。
勘のいい方はお分かりでしょう。これはAIにとって優しい仕組みです。Webのページをフェッチした時についてくるHTMLタグがありません。標準出力なのでAIコーディングエージェントが読むことができます。
hono search
次に紹介するのはhono search
です。
hono search <query>
query
には検索語を指定します。例えば、ミドルウェアに関するドキュメントのありかを調べたければ、こうします。
hono search middleware
すると、検索語に関係のあるWebサイトのURLとパスがJSONフォーマットで標準出力に表示されます。
ということは、hono docs
と組み合わせると「AIが自律してドキュメントを検索して読む」ことができるわけです。例えば、ベーシック認証のドキュメントを調べて読むにはこのような流れになります。
hono search "basic auth"
-
/docs/middleware/builtin/basic-auth
というパスを取得 -
hono docs
の引数に渡す - 該当のドキュメントのMarkdownが表示される
AI向けのコマンドはこれだけではありません。次に行きましょう。
hono request
次のコマンドはhono request
です。
hono request [file]
file
のデフォルト値はsrc/index.ts
なのですが、明示的に指定するにはこうします。
hono request src/index.ts
このコマンドを理解するために、まずHonoのAPIである「app.request()
」をイメージしてください。app.request()
を使うとサーバーを立ち上げずに、Honoアプリにリクエストを飛ばし、そのレスポンスを取得することができます。これは動作確認やテストなどに非常に便利です。
以下はパス/
にGETリクエストを送り、返ってきたResponse
オブジェクトがres
に入るというコードです。
const res = await app.request('/')
hono request
は引数で指定したファイル内にあるHonoのアプリに対して、コマンドラインで指定したリクエストを飛ばしてその結果を印字します。
hono request src/index.ts
とすると、
const res = await app.request('/')
が実行されるわけです。例えば、Hello Worldアプリがあります。
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello World'))
export default app
ではこのファイルにhono request
してみましょう。
-P
でリクエストするパス/
を指定してます。デフォルトのメソッドはGETです。標準出力にはJSONフォーマットで「ステータス・コードは200
、ボディはHello World
」という結果が印字されています。より複雑なことができます。curl
ライクに-X
でメソッド指定、-d
でボディを指定することができます。
hono request \
-P /api/users \
-X POST \
-d '{"name":"Alice"}' \
src/index.ts
このコマンドは人間にとって非常に便利です。これまでアプリの試験をする場合はWranglerやDeno、Bun、Node.jsのコマンドを使ってサーバーを立ち上げ、Webブラウザやcurl
などのクライアントで叩いてました。ところがこのhono request
を使うとサーバーを立ち上げずにアプリを試験することができるのです!
AIも使うことができます。これは非常に強力です。コーディングエージェントがサーバーを立ち上げて、curl
を叩く様子をあなたも見たことがあるでしょう。サーバーのシャットダウンがうまくいかずにポートが被って、何個もサーバーを立ち上げる様子も... hono request
を使うと、サーバーすら立ち上げる必要がないので、非常に高速で、正確で、クリーンにアプリをテストすることができます。
そして、AIは先程でてきた2つのコマンドとこのコマンドを組み合わせて使うことができます。つまりこういうことです。
-
hono search
=> ドキュメントを探す -
hono docs
=> ドキュメントを読む -
hono request
=> アプリを試験する
このワークフローをAGENTS.md
やCLAUD.md
に手順として書いておくことができます。これはそのまま使えます。
# My App Development Guidelines
## Hono Development
Use the `hono` CLI for efficient development. View all commands with `hono --help`.
### Core Commands
- **`hono docs [path]`** - Browse Hono documentation
- **`hono search <query>`** - Search documentation
- **`hono request [file]`** - Test app requests without starting a server
### Quick Examples
```bash
# Search for topics
hono search middleware
hono search "getting started"
# View documentation
hono docs /docs/api/context
hono docs /docs/guides/middleware
# Test your app
hono request -P /api/users src/index.ts
hono request -P /api/users -X POST -d '{"name":"Alice"}' src/index.ts
```
### Workflow
1. Search documentation: `hono search <query>`
2. Read relevant docs: `hono docs [path]`
3. Test implementation: `hono request [file]`
デモを見てください。コーディングエージェントがhono
コマンドを活用して、アプリを作成している様子が分かるでしょう。
hono serve
これまではAIのためのコマンドでした。次に人間のためのコマンドを紹介しましょう。最初のコマンドはhono serve
です。
hono search index.ts
すると、index.ts
のHonoアプリがhttp://localhost:7070
で立ち上がります。
??それだけですか??それってNode.js Adapterを挟む必要がなくなっただけで、WranglerやDeno、Bunでも同じ事できますよね?
いえ、--use
というオプションがあります。app.use()
を想像してみてください。
app.use(middleware)
app.use()
は渡されたミドルウェアをアプリに適応します。例えば、ビルドインのロガーミドルウェアはこのように使います。
app.use(logger())
そこからlogger()
を取り出してみます。hono serve
では--use
オプションの値にそれを指定して、アプリのコードを変えずともミドルウェアを適応することができます。
hono --use 'logger()' src/index.ts
このようにすると、ロガーを指定していないアプリでもログが出てきます。
これを応用すると、コードを書き換えずにBasic認証を追加する、なんてこともできます。
hono serve \
--use "logger()" \
--use "basicAuth({username:'foo',password:'bar'})" \
src/index.ts
さて、このサブコマンドではsrc/index.ts
などのエントリパスを渡さないと空のアプリが使われます。
http://localhost:7070
にアクセスすると404
になります。これを応用すると、手元にファイルがなくてもミドルウェアを組み合わせたサーバーを立ち上げることができます。
例えば、手元のファイルをサーブするサーバーを立ち上げられます。
hono serve \
--use "serveStatic({root:'./'})"
ヘルパーを使うことも可能なので、Proxyヘルパーのproxy
を利用してRamen APIのリバースプロキシを立てることもできます。
hono serve \
--use '(c) => proxy(`https://ramen-api.dev${new URL(c.req.url).pathname}`)'
hono optimize
最後のコマンドはhono optimize
です。
hono optimize [entry]
コマンドの説明の前にHonoのルーターについて話しましょう。RegExpRouterはJavaScript界の高速なルーターのうちの一つです。条件によっては1位の速さをほこります。RegExpRouterのアイデアはダイナミックルートの情報を一つの大きな正規表現にして、リクエストが来たら一度にマッチさせるということです。これには弱点があります。
- 初期化が遅い
- ファイルサイズは大きくなる
それぞれを解決するために、Honoでは2つのルーターが発明され、それぞれプリセットという形で提供されています。
- LinearRouter -
hono/quick
- PatternRouter -
hono/tiny
確かに、LinearRouterは初期化込みのベンチでは速く、PatternRouterのバンドルサイズは小さいです。しかし、私はRegExpRouterを使いたいのです!
そこで今日は7つの目の(6個は今ある5個のルーターと廃止になったStaticRouter)ルーターを紹介します。PreparedRegExpRouterです。
PreparedRegExpRouterのアイデアは、RegExpRouterの時に作る正規表現相当のルート情報を予め文字列にしてハードコードするというものです。
このようなアプリがあったとします。
import { Hono } from 'hono'
const app = new Hono()
app.get('/posts', (c) => c.json({}))
app.get('/posts/:id', (c) => c.json({}))
app.put('/posts', (c) => c.json({}))
export default app
このルート情報を予め文字列にしてルーターのコンストラクタに渡します。
const routerParams = [
{ ALL: [/^\/posts\/([^/]+)$()/, [0, 0, []], { '/posts': [[], []] }] },
{ '/posts': [[['']]], '/posts/:id': [[[2], { id: 1 }]] }
]
const router = new PreparedRegExpRouter(...routerParams)
これでまず初期化が速くなりました。初期化を含めたルーターのパフォーマンスを測るベンチマーク結果を見てみましょう。
これを並べ替えると...
LinearRouterは流石に一位ですが、PreparedRegExpRouterが2位につけています。RegExpRouterはだいぶ後ろです。比べるとPrepareRegExpRouterはRegExpRouterに比べて(初期化を含んだベンチマークで)16.5倍速くなっています。
Hono CLIの話に戻りましょう。
hono optimize
は「あなたのアプリの"Honoを"最適化します」。では最適化されたHonoとは一体なんでしょうか?それはこれです。
class Hono extends HonoBase {
constructor(options = {}) {
super(options)
const routerParams = [
{ ALL: [/^\/posts\/([^/]+)$()/, [0, 0, []], { '/posts': [[], []] }] },
{ '/posts': [[['']]], '/posts/:id': [[[2], { id: 1 }]] }
]
this.router = new PreparedRegExpRouter(...routerParams)
}
}
つまり、そのアプリに合わせたPreparedRegExpRouterが実装されたHonoになります。
hono optimize
を実行してみましょう。
すると、dist/index.js
にsrc/index.ts
の最適化された結果が書き出されます。これをそのままwrangler deploy
するイメージです。
hono optimize src/index.ts
wrangler deploy dist/index.js
ではどのくらい小さくなったのか?最適化なしでビルドしてミニファイしたものと、hono optimize
をminify
オプションで実行したファイル、更にhono/tiny
のプリセットを使ったものと比べてみます。
hono/tiny
のサイズには及ばないものの、元アプリの18.0KB
に対して、11.14KB
とかなり小さくなっています。値にすると38%分小さくなりました。
つまりhono optimize
はあなたのアプリを速く、小さくするのです。このようにHono CLIはhono serve
とhono optimize
という人間向けのシンプルなサブコマンドを提供します。
まとめ
以上、Hono CLIは5つのサブコマンドを提供します。
hono docs
hono search
hono request
hono serve
hono optimize
これらは人間とAIのためのコマンドです。
Hono CLIのレポジトリは公開されています。
そして、今すぐあなたもHono CLIを試すことができます。
npm i @hono/cli
では、楽しんでください。
Discussion