Hono v4.12.0
Hono v4.12.0がリリースされました!このリリースには、Honoクライアントの新機能、ミドルウェアの改善、アダプターの拡張、そしてルーターとコンテキストの大幅なパフォーマンス向上が含まれています。
Honoクライアント用の$path
Honoクライアントに、完全なURLではなくパス文字列を返す$path()メソッドが追加されました。これは、ルーティングやキーベースの操作でパス部分のみが必要な場合に便利です:
const client = hc<typeof app>('http://localhost:8787')
const path = client.api.posts.$path()
const postPath = client.api.posts[':id'].$path({
param: { id: '123' },
})
const searchPath = client.api.posts.$path({
query: { filter: 'test' },
})
URLオブジェクトを返す$url()とは異なり、$path()はプレーンなパス文字列を返すため、ルーターでの使用やキャッシュキーとして便利です。
@ShaMan123 さん、ありがとうございます!
RPCクライアント用のApplyGlobalResponseタイプヘルパー
新しいApplyGlobalResponseタイプヘルパーにより、RPCクライアントのすべてのルートにグローバルエラーレスポンスタイプを追加できます。これは、app.onError()やグローバルミドルウェアからの共通エラーレスポンスをタイピングする際に便利です:
const app = new Hono()
.get('/api/users', (c) => c.json({ users: ['alice', 'bob'] }, 200))
.onError((err, c) => c.json({ error: err.message }, 500))
type AppWithErrors = ApplyGlobalResponse<
typeof app,
{
401: { json: { error: string; message: string } }
500: { json: { error: string; message: string } }
}
>
const client = hc<AppWithErrors>('http://api.example.com')
const res = await client.api.users.$get()
@mohankumarelec さん、ありがとうございます!
SSGリダイレクトプラグイン
SSG用の新しいredirectPluginは、HTTPリダイレクトレスポンス(301、302、303、307、308)用の静的HTMLリダイレクトページを生成します:
import { toSSG } from 'hono/ssg'
import { defaultPlugin, redirectPlugin } from 'hono/ssg'
const app = new Hono()
app.get('/old', (c) => c.redirect('/new'))
app.get('/new', (c) => c.html('New Page'))
await toSSG(app, fs, {
plugins: [redirectPlugin(), defaultPlugin()],
})
生成されるリダイレクトページには、<meta http-equiv="refresh">タグ、canonicalリンク、robots noindexメタタグが含まれます。
@3w36zj6 さん、ありがとうございます!
Basic Auth用のonAuthSuccessコールバック
Basic Authミドルウェアに、認証成功後に呼び出されるonAuthSuccessコールバックがサポートされました。これにより、Authorizationヘッダーを再解析することなく、コンテキスト変数の設定やログ記録が可能になります:
app.use('/auth/*', basicAuth({
username: 'hono',
password: 'ahotproject',
onAuthSuccess: (c, username) => {
c.set('user', { name: username, role: 'admin' })
console.log(`User ${username} authenticated`)
},
}))
コールバックは非同期関数やverifyUserモードでも動作します。
@AprilNEA さん、ありがとうございます!
AWS Lambda、Cloudflare Pages、Netlify用のgetConnInfo
getConnInfo()が3つの追加アダプターで利用可能になりました:
import { handle, getConnInfo } from 'hono/aws-lambda'
import { handle, getConnInfo } from 'hono/cloudflare-pages'
import { handle, getConnInfo } from 'hono/netlify'
app.get('/', (c) => {
const info = getConnInfo(c)
return c.text(`Your IP: ${info.remote.address}`)
})
@rokasta12 さん、ありがとうございます!
Trailing Slashミドルウェア用のalwaysRedirectオプション
trailing slashミドルウェアにalwaysRedirectオプションがサポートされました。有効にすると、ミドルウェアはハンドラー実行前にリダイレクトを行い、ワイルドカードルートでtrailing slash処理が動作しない問題を修正します:
app.use(trimTrailingSlash({ alwaysRedirect: true }))
app.get('/my-path/*', async (c) => {
return c.text('wildcard')
})
プログレッシブロケールコード切り詰め
languageミドルウェアのnormalizeLanguage関数で、RFC 4647 Lookupベースのプログレッシブ切り詰めがサポートされました。ja-JPのようなロケールコードは、supportedLanguagesにベース言語のみがある場合、jaにマッチします:
app.use('/*', languageDetector({
supportedLanguages: ['en', 'ja'],
fallbackLanguage: 'en',
order: ['cookie', 'header'],
}))
@sorafujitani さん、ありがとうございます!
ExecutionContext用のexportsフィールド
ExecutionContextタイプにCloudflare Workers用のexportsプロパティが含まれました。モジュール拡張を使用してWranglerの生成タイプでタイピングできます:
import 'hono'
declare module 'hono' {
interface ExecutionContext {
readonly exports: Cloudflare.Exports
}
}
@toreis-up さん、ありがとうございます!
パフォーマンス改善
TrieRouterが1.5倍〜2.0倍高速化
TrieRouterは、スプレッド構文の使用削減、O(1)のhasChildrenチェック、遅延正規表現生成、冗長プロセスの除去により大幅に最適化されました:
| ルート | Node.js | Deno | Bun |
|---|
| short static GET /user | 1.70x | 1.40x | 1.34x |
| dynamic GET /user/lookup/username/hey | 1.38x | 1.69x | 1.51x |
| wildcard GET /static/index.html | 1.51x | 1.72x | 1.43x |
| all together | 1.58x | 1.60x | 1.82x |
@EdamAme-x さん、ありがとうございます!
c.json()の高速パス
c.json()にc.text()と同じ高速パス最適化が追加されました。カスタムステータス、ヘッダー、または確定状態が存在しない場合、Headersオブジェクトを割り当てることなく直接Responseが作成されます:
return c.json({ message: 'Hello' })
ベンチマーク結果:
| メトリック | 変更前 | 変更後 | 変化 |
|---|
| Reqs/sec | 92,268 | 95,244 | +3.2% |
| Latency | 5.42ms | 5.25ms | -3.1% |
| Throughput | 17.24MB/s | 19.07MB/s | +10.6% |
@mgcrea さん、ありがとうございます!
新機能
- feat(client): RPCクライアント用のApplyGlobalResponseタイプヘルパーを追加 #4556
- feat(ssg): リダイレクトプラグインを追加 #4599
- feat(client): $path #4636
- feat(basic-auth): コンテキストキーとコールバックオプションを追加 #4645
- feat(adapter): AWS Lambda、Cloudflare Pages、Netlify用のgetConnInfoを追加 #4649
- feat(trailing-slash): ワイルドカードルートをサポートするalwaysRedirectオプションを追加 #4658
- feat(language): normalizeLanguageにプログレッシブロケールコード切り詰めを追加 #4717
- feat(types): ExecutionContextにexportsフィールドを追加 #4719
パフォーマンス
- perf(context): c.text()最適化に合わせてc.json()に高速パスを追加 #4707
- perf(trie-router): パフォーマンス改善(1.5倍〜2.0倍) #4724
- perf(context): 新しいResponseにcreateResponseInstanceを使用 #4733
すべての変更
- fix(jsx/dom): render children loopで空配列を処理 by @mixelburg in #4729
- perf(jsx/dom): 繰り返しflatteningを避けるため開始時に一度childrenをflatten by @usualoma in #4730
- fix(client): フォームデータシリアライゼーションでundefined値をスキップ by @aidenlx in #4732
- feat(client): RPCクライアント用のApplyGlobalResponseタイプヘルパーを追加 by @mohankumarelec in #4556
- feat(ssg): リダイレクトプラグインを追加 by @3w36zj6 in #4599
- feat(client): $path by @ShaMan123 in #4636
- feat(basic-auth): コンテキストキーとコールバックオプションを追加 by @AprilNEA in #4645
- feat(adapter): AWS Lambda、Cloudflare Pages、Netlify用のgetConnInfoを追加 by @rokasta12 in #4649
- feat(trailing-slash): ワイルドカードルートをサポートするalwaysRedirectオプションを追加 by @yusukebe in #4658
- perf(context): c.text()最適化に合わせてc.json()に高速パスを追加 by @mgcrea in #4707
- feat(language): normalizeLanguageにプログレッシブロケールコード切り詰めを追加 by @sorafujitani in #4717
- feat(types): ExecutionContextにexportsフィールドを追加 by @toreis-up in #4719
- perf(trie-router): パフォーマンス改善(1.5倍〜2.0倍) by @EdamAme-x in #4724
- perf(context): 新しいResponseにcreateResponseInstanceを使用 by @yusukebe in #4733
- Next by @yusukebe in #4735
新しいコントリビューター
- @mixelburg が #4729 で初回コントリビュート
- @aidenlx が #4732 で初回コントリビュート
- @mohankumarelec が #4556 で初回コントリビュート
- @ShaMan123 が #4636 で初回コントリビュート
- @rokasta12 が #4649 で初回コントリビュート
- @mgcrea が #4707 で初回コントリビュート
Full Changelog: v4.11.10...v4.12.0