Do Everything, Run Anywhere, But Small, And Faster.
Hono v3.0.0 has been released now! Introduce the new features.
Note
There are some breaking changes. See the migration guide.
HonoRequest
Previously, c.req
was an extended Request
object. But, the functions and types vary by runtime. So it was causing inconvenience.
Hence, HonoRequest
is born.
HonoRequest
has Hono-specific functions such as req.param()
and req.query
, then will wrap the Request
object. You can access the original Response
object via req.raw
. Most functions and properties are bypassed, so you can still use c.req
as before.
// c.req is HonoRequest
const id = c.req.param('id')
const query = c.req.query('q')
const data = await c.req.json()
// originalRequest is Request
const originalRequest = c.req.raw
Performance improvement
It is getting 2% - 11% faster. So, Hono is fast.
RegExpRouter becomes the fastest router
RegExpRouter become the fastest router in the JavaScript world which includes such "find-my-way" used in Fastify.
You can find the benchmark scripts.
Good-bye StaticRouter
Thanks to the faster RegExpRouter, StaticRouter is no longer needed. Obsolete. Good-bye StaticRouter!
New Validator
The previous Validator Middleware is obsolete and you can use the new validator. Its validator is very thin and we recommend using it with a third-party validator.
If you want to use Zod, now, we have "Zod Validator Middleware".
import { zValidator } from '@hono/zod-validator'
import { Hono } from 'hono'
import { z } from 'zod'
const app = new Hono()
app.post(
'/posts',
zValidator(
'json',
z.object({
id: z.number(),
title: z.string(),
})
),
(c) => {
const { id, title } = c.req.valid('json')
return c.text(`${id} is ${title}!`)
}
)
RPC
Then, we'll show you the magic.
output.mov
We've made the HTTP client which is called hc
. API specs can be shared as types between the API server and the client. It is like tRPC, but easier to handle due to its being integrated.
To enable RPC mode, simply change json()
to jsonT()
and share the endpoint type.
// server.ts
const route = app.post(
'/posts',
zValidator(
'json',
z.object({
id: z.number(),
title: z.string(),
})
),
(c) => {
const { id, title } = c.req.valid('json')
// ...
return c.jsonT(
{
success: true,
message: 'created!',
},
201
)
}
)
export type AppType = typeof route
On the client side, import the type and pass it to hc()
as a generics.
import { hc } from 'hono/client'
import type { AppType } from './index'
const client = hc<AppType>('/api')
Now it is ready for use. See it.
Thanks
This RPC feature is based on @cleaton's comment.
Thanks for the ultra-cool idea.
Adapter
Hono is also suitable for running in functions
of Cloudflare Pages or in Edge Functions of Next.js. To make them easier, you can use the "Adapter".
// pages/api/[...route].ts
import { Hono } from 'hono'
import { handle } from 'hono/nextjs'
export const config = {
runtime: 'edge',
}
const app = new Hono()
app.get('/hello', (c) => {
return c.json({
message: 'Hello from Hono!',
})
})
export default handle(app, '/api')
The combination of this adapter and RPC is powerful. You can write the REST API on the Edge Functions and write the React applications with hc
.
Also, ServeStatic Middleware has been obsolete and the feature of serving static files is now provided via an Adapter.
import { Hono } from 'hono'
import { serveStatic } from 'hono/cloudflare-workers'
const app = new Hono()
app.get('/static/*', serveStatic({ root: './' }))
app.get('/favicon.ico', serveStatic({ path: './favicon.ico' }))
HTTPException
The new HTTPException
makes your application safer.
Multi-runtime CI support
Hono works on most JavaScript runtimes. It becomes to be tested on the CI for the following five runtimes.
Support WinterCG Runtime Keys
Hono is following WinterCG and will be "de fact standard for Web Standard". Now, c.runtime()
supports WinterCG's Runtime Keys.
app.get('/', (c) => {
if (c.runtime === 'workerd') {
return c.text('You are on Cloduflare')
} else if (c.runtime === 'bun') {
return c.text('You are on Bun')
}
...
})
Available runtime keys are below.
node
deno
bun
workerd
- Cloudflare Workersfastly
edge-light
- Vercel Edge Functionslagon
other
create-hono
You can create the Hono application with one command and launch the application in 30 seconds!
npm create hono@latest my-app
@honojs
to @hono
@honojs
namespace in the Npm registry is deprecated, but we can use @hono
! So each Middleware is now renamed as follows.
@hono/graphql-server
@hono/sentry
@hono/firebase-auth
And Node.js adapter becomes @hono/node-server
.
New middleware
Adding them, we can use these new middleware.
@hono/trpc-server
- tRPC Server Middleware@hono/qwik-city
- Qwik City Middleware@hono/zod-validator
- Zod Validator Middleware
New website
Finally, we have to tell you about it. We have the new website with an ultra cool domain name.
hono.dev!!
Not only the domain but has been changed from Hugo-based to VitePress-based, making it easier to contribute.
Wrap-up
Many new features. Enjoy and share!
All Changes
- build: validate package exports after build by @yudai-nkt in #824
- fix(request): make optional param type correct by @yusukebe in #826
- perf: use
substring
and//.test
... by @yusukebe in #829 - fix(bun): fixed throwing the error in
HTTPException
by @yusukebe in #830 - feat(validator): support multiple handlers w/ complex patterns. by @yusukebe in #831
- feat(req): support
c.req.valid('query')
by @yusukebe in #832 - fix(context): set the header values of already set by @yusukebe in #834
- fix(context): fixed bug raw
Response
content-type is overwritten by @yusukebe in #836 - Missing mime types by @Hoodgail in #827
- fix(cloudflare-pages): fix type incompatibility by @yusukebe in #837
- feat(reg-exp-router): Lookup static path by using Object by @usualoma in #845
- chore: benchmark of routers by @yusukebe in #843
- Rename runtime keys by @yujong-lee in #850
- feat: rewnew output types by @yusukebe in #853
- fix(breaking): obsolete no args
c.req.valid()
by @yusukebe in #856 - refactor(request): don't cache jsonBody, formBody, and headers by @yusukebe in #857
- fix(req):
never
ifc.req.valid()
by @yusukebe in #859 - perf(context): improve handling response by @yusukebe in #860
- refactor: obsolute
CustomHandler
by @yusukebe in #861 - Fix 404 error on Serve Static Middleware by @BioniCosmos in #863
- fix(serve-static): decode url pathname by @yusukebe in #864
- chore: denoify by @yusukebe in #865
- perf(reg-exp-router): Cache Result instead of T[] if there is no parameter. by @usualoma in #867
- feat:
hc
- Hono Client by @yusukebe in #862 - feat: use added app's errorHandler by @usualoma in #871
- Revert "feat: use added app's errorHandler (#871)" by @yusukebe in #872
- feat: Remove the StaticRouter from default candidates. by @usualoma in #869
- feat(router) [breaking]: StaticRouter obsolete by @yusukebe in #873
- feat: use added app's errorHandler with comose() by @usualoma in #874
- merge main into next by @yusukebe in #876
- feat(adapter):
handle(path, app)
for CF Pages & Next.js by @yusukebe in #878 - feat(validator): moved validator outside of middleware by @yusukebe in #879
- chore: update Deno benchmark by @yusukebe in #880
- feat(adapter)!: simplify HandleInterface and reduce bundle size by @yudai-nkt in #881
- feat(
app
): support multiple methods withapp.on()
by @yusukebe in #882 - feat: move http-exception out of utils by @yusukebe in #883
- fix(deno): allow
{}
forapp.fetch
fo compatibility by @yusukebe in #887 - header may return undefined by @AlexErrant in #884
- fix(req): query return type as
string | undefined
by @yusukebe in #888 - refactor: rename to
TypedResponse
by @yusukebe in #889 - refactor: rename
ValidationTypes
toValidationTargets
by @yusukebe in #890 - docs(readme): add bundlephobia badges by @yusukebe in #891
- feat: change the arg
InferResponseType
receives by @yusukebe in #893 - feat(client): introduce
Fetch
type by @yusukebe in #898 - refactor(req): remove
async
keyword fromjson()
etc. by @yusukebe in #899 - chore:
honojs.dev
tohono.dev
by @yusukebe in #900 - fix(jsx): declare types for JSX correctly by @yusukebe in #901
- docs(readme): update for v3 by @yusukebe in #902
- docs: update migration guide for v3 by @yusukebe in #903
- docs(migration): add descriptions by @yusukebe in #904
- v3 by @yusukebe in #905
New Contributors
- @Hoodgail made their first contribution in #827
- @BioniCosmos made their first contribution in #863
- @AlexErrant made their first contribution in #884
Full Changelog: v2.7.3...v3.0.0