v4.12.0
honojs/honov4.12.0Feb 19, 2026by yusukebe
AI Summary
A feature-rich release with new client capabilities, middleware improvements, adapter enhancements, and significant performance optimizations including 1.5x-2x faster TrieRouter and 10.6% improved JSON throughput.
Key Highlights
- $path method for Hono Client - returns path string for routing and cache keys
- ApplyGlobalResponse type helper for adding global error response types to RPC client
- SSG redirect plugin for generating static HTML redirect pages
- onAuthSuccess callback for Basic Auth middleware
- getConnInfo available for AWS Lambda, Cloudflare Pages, and Netlify adapters
- alwaysRedirect option for trailing slash middleware with wildcard routes
- Progressive locale code truncation in language middleware
- TrieRouter performance improved 1.5x-2.0x across all runtimes
- Fast path optimization for c.json() with 10.6% throughput improvement
New Features
- $path() method for Hono Client
- ApplyGlobalResponse type helper for RPC Client
- SSG redirect plugin
- onAuthSuccess callback for Basic Auth
- getConnInfo for AWS Lambda, Cloudflare Pages, and Netlify
- alwaysRedirect option for trailing slash middleware
- Progressive locale code truncation for language middleware
- exports field for ExecutionContext in Cloudflare Workers
Full Release Notes
# Release Notes
Hono v4.12.0 is now available!
This release includes new features for the Hono client, middleware improvements, adapter enhancements, and significant performance improvements to the router and context.
## `$path` for Hono Client
The Hono client now has a `$path()` method that returns the path string instead of a full URL. This is useful when you need just the path portion for routing or key-based operations:
```ts
const client = hc<typeof app>('http://localhost:8787')
// Get the path string
const path = client.api.posts.$path()
// => '/api/posts'
// With path parameters
const postPath = client.api.posts[':id'].$path({
param: { id: '123' },
})
// => '/api/posts/123'
// With query parameters
const searchPath = client.api.posts.$path({
query: { filter: 'test' },
})
// => '/api/posts?filter=test'
```
Unlike `$url()` which returns a `URL` object, `$path()` returns a plain path string, making it convenient for use with routers or as cache keys.
Thanks @ShaMan123!
## `ApplyGlobalResponse` Type Helper for RPC Client
The new `ApplyGlobalResponse` type helper allows you to add global error response types to all routes in the RPC client. This is useful for typing common error responses from `app.onError()` or global middlewares:
```ts
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')
// Now client knows about both success and error responses
const res = await client.api.users.$get()
// InferResponseType includes { users: string[] } | { error: string; message: string }
```
Thanks @mohankumarelec!
## SSG Redirect Plugin
A new `redirectPlugin` for SSG generates static HTML redirect pages for HTTP redirect responses (301, 302, 303, 307, 308):
```ts
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'))
// redirectPlugin must be placed before defaultPlugin
await toSSG(app, fs, {
plugins: [redirectPlugin(), defaultPlugin()],
})
```
The generated redirect pages include a `<meta http-equiv="refresh">` tag, a canonical link, and a `robots noindex` meta tag.
Thanks @3w36zj6!
## `onAuthSuccess` Callback for Basic Auth
The Basic Auth middleware now supports an `onAuthSuccess` callback that is invoked after successful authentication. This allows you to set context variables or perform logging without re-parsing the Authorization header:
```ts
app.use(
'/auth/*',
basicAuth({
username: 'hono',
password: 'ahotproject',
onAuthSuccess: (c, username) => {
c.set('user', { name: username, role: 'admin' })
console.log(`User ${username} authenticated`)
},
})
)
```
The callback also works with async functions and the `verifyUser` mode.
Thanks @AprilNEA!
## `getConnInfo` for AWS Lambda, Cloudflare Pages, and Netlify
`getConnInfo()` is now available for three additional adapters:
```ts
// AWS Lambda (supports API Gateway v1, v2, and ALB)
import { handle, getConnInfo } from 'hono/aws-lambda'
// Cloudflare Pages
import { handle, getConnInfo } from 'hono/cloudflare-pages'
// Netlify
import { handle, getConnInfo } from 'hono/netlify'
app.get('/', (c) => {
const info = getConnInfo(c)
return c.text(`Your IP: ${info.remote.address}`)
})
```
Thanks @rokasta12!
## `alwaysRedirect` Option for Trailing Slash Middleware
The trailing slash middleware now supports an `alwaysRedirect` option. When enabled, the middleware redirects before executing handlers, which fixes the issue where trailing slash handling doesn't work with wildcard routes:
```ts
app.use(trimTrailingSlash({ alwaysRedirect: true }))
app.get('/my-path/*', async (c) => {
return c.text('wildcard')
})
// /my-path/something/ will be redirected to /my-path/something
// before the wildcard handler is executed
```
## Progressive Locale Code Truncation
The `normalizeLanguage` function in the language middleware now supports RFC 4647 Lookup-based progressive truncation. Locale codes like `ja-JP` will match `ja` when only the base language is in `supportedLanguages`:
```ts
app.use(
'/*',
languageDetector({
supportedLanguages: ['en', 'ja'],
fallbackLanguage: 'en',
order: ['cookie', 'header'],
})
)
// Accept-Language: ja-JP → matches 'ja'
// Accept-Language: ko-KR → falls back to 'en'
```
Thanks @sorafujitani!
## `exports` Field for `ExecutionContext`
The `ExecutionContext` type now includes an `exports` property for Cloudflare Workers. You can use module augmentation to type it with Wrangler's generated types:
```ts
import 'hono'
declare module 'hono' {
interface ExecutionContext {
readonly exports: Cloudflare.Exports
}
}
```
Thanks @toreis-up!
## Performance Improvements
### TrieRouter 1.5x ~ 2.0x Faster
The TrieRouter has been significantly optimized with reduced spread syntax usage, O(1) `hasChildren` checks, lazy regular expression generation, and removal of redundant processes:
| Route | 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** |
Thanks @EdamAme-x!
### Fast Path for `c.json()`
`c.json()` now has the same fast path optimization as `c.text()`. When no custom status, headers, or finalized state exists, the Response is created directly without allocating a `Headers` object:
```ts
// This common pattern is now faster
return c.json({ message: 'Hello' })
```
Benchmark results:
| Metric | Before | After | Change |
| ---------- | --------- | --------- | ---------- |
| Reqs/sec | 92,268 | 95,244 | **+3.2%** |
| Latency | 5.42ms | 5.25ms | **-3.1%** |
| Throughput | 17.24MB/s | 19.07MB/s | **+10.6%** |
Thanks @mgcrea!
## New features
- feat(client): Add `ApplyGlobalResponse` type helper for RPC Client https://github.com/honojs/hono/pull/4556
- feat(ssg): add redirect plugin https://github.com/honojs/hono/pull/4599
- feat(client): $path https://github.com/honojs/hono/pull/4636
- feat(basic-auth): add context key and callback options https://github.com/honojs/hono/pull/4645
- feat(adapter): add getConnInfo for AWS Lambda, Cloudflare Pages, and Netlify https://github.com/honojs/hono/pull/4649
- feat(trailing-slash): add `alwaysRedirect` option to support wildcard routes https://github.com/honojs/hono/pull/4658
- feat(language): add progressive locale code truncation to normalizeLanguage https://github.com/honojs/hono/pull/4717
- feat(types): Add exports field to ExecutionContext https://github.com/honojs/hono/pull/4719
## Performance
- perf(context): add fast path to c.json() matching c.text() optimization https://github.com/honojs/hono/pull/4707
- perf(trie-router): improve performance (1.5x ~ 2.0x) https://github.com/honojs/hono/pull/4724
- perf(context): use `createResponseInstance` for new Response https://github.com/honojs/hono/pull/4733
## All changes
- fix(jsx/dom): handle empty arrays in render children loop by @mixelburg in https://github.com/honojs/hono/pull/4729
- perf(jsx/dom): flatten children once at the start to avoid repeated flattening by @usualoma in https://github.com/honojs/hono/pull/4730
- fix(client): skip undefined values in form data serialization by @aidenlx in https://github.com/honojs/hono/pull/4732
- feat(client): Add `ApplyGlobalResponse` type helper for RPC Client by @mohankumarelec in https://github.com/honojs/hono/pull/4556
- feat(ssg): add redirect plugin by @3w36zj6 in https://github.com/honojs/hono/pull/4599
- feat(client): $path by @ShaMan123 in https://github.com/honojs/hono/pull/4636
- feat(basic-auth): add context key and callback options by @AprilNEA in https://github.com/honojs/hono/pull/4645
- feat(adapter): add getConnInfo for AWS Lambda, Cloudflare Pages, and Netlify by @rokasta12 in https://github.com/honojs/hono/pull/4649
- feat(trailing-slash): add `alwaysRedirect` option to support wildcard routes by @yusukebe in https://github.com/honojs/hono/pull/4658
- perf(context): add fast path to c.json() matching c.text() optimization by @mgcrea in https://github.com/honojs/hono/pull/4707
- feat(language): add progressive locale code truncation to normalizeLanguage by @sorafujitani in https://github.com/honojs/hono/pull/4717
- feat(types): Add exports field to ExecutionContext by @toreis-up in https://github.com/honojs/hono/pull/4719
- perf(trie-router): improve performance (1.5x ~ 2.0x) by @EdamAme-x in https://github.com/honojs/hono/pull/4724
- perf(context): use `createResponseInstance` for new Response by @yusukebe in https://github.com/honojs/hono/pull/4733
- Next by @yusukebe in https://github.com/honojs/hono/pull/4735
## New Contributors
- @mixelburg made their first contribution in https://github.com/honojs/hono/pull/4729
- @aidenlx made their first contribution in https://github.com/honojs/hono/pull/4732
- @mohankumarelec made their first contribution in https://github.com/honojs/hono/pull/4556
- @ShaMan123 made their first contribution in https://github.com/honojs/hono/pull/4636
- @rokasta12 made their first contribution in https://github.com/honojs/hono/pull/4649
- @mgcrea made their first contribution in https://github.com/honojs/hono/pull/4707
**Full Changelog**: https://github.com/honojs/hono/compare/v4.11.10...v4.12.0