Skip to content

Hono.js

Introduction

This document provides an overview of Hono.js, a small, simple and ultrafast web framework. It works on any JavaScript runtime, including Cloudflare Workers.

Features:

  • Ultrafast - The router RegExpRouter is really fast. Not using linear loops. Fast
  • Lightweight - The hono/tiny preset in under 14kB. Hono has zero dependencies and uses only the Web Standards.
  • Multi-runtime - Works on Cloudflare Workers, AWS Lambda etc. The same code runs on all platforms.
  • Batteries Included - Hono has built-in middleware, custom middleware, third-party middleware and helpers.
  • Delightful DX - Super clean APIs. First-class TypeScript support.
  • Multiple routers - RegExpRouter is the fastest router in the JavaScript world. It matches the route using a single large Regex created before dispatch. With SmartRouter it supports all route patterns. LinearRouter registers the routes very quickly, so it's suitable for an environment that initializes applications every time. PatternRouter simply adds and matches the pattern, making it small.

Use-cases

  • Building Web APIs
  • Proxy of backend servers
  • Front of CDN
  • Edge application
  • Full-stack application

Middleware & Helpers


Routers

The routers are the most important features for Hono. Hono.js has five routers.

RegExpRouter

The RegExpRouter is the fastest router in the JavaScript world. It turns the route pattern into "one large regular expression". Then it can get the result with one-time matching. This works faster than methods that use tree-based algorithms such as radix-tree in most cases.

TrieRouter

The TrieRouter is the router using the Trie-tree algorithm. It does not use linear loops as same as RegExpRouter. The router is not as fast as the RegExpRouter, but it is much faster than the Express router. TrieRouter supports all patterns though RegExpRouter does not.

SmartRouter

RegExpRouter does not support all routing patterns. Therefore, it's usually used in combination with another router that does support all patterns.

SmartRouter will select the best router by inferring from the registered routers. Hono uses SmartRouter and the two routers by default.

typescript
// Inside the core of Hono.
readonly defaultRouter: Router = new SmartRouter({
  routers: [new RegExpRouter(), new TrieRouter()],
})

TIP

When the application starts, SmartRouter detects the fastest router based on routing and continues to use it.

LinearRouter

RegExpRouter is fast, but the route registration phase can be slightly slow. So, it's not suitable for an environment that initializes with every request.

LinearRouter is optimized for "one shot" situations. Route registration is significantly faster than RegExpRouter because it adds the route without compiling strings, using a linear approach.

TIP

For situations like Fastly Compute, it is better to use LinearRouter with the hono/quick preset.

PatternRouter

PatternRouter is the smallest router among Hono's routers. While Hono is already compact, if you need to make it even smaller for an environment with limited resources you can use PatternRouter.

TIP

An application using only PatternRouter is under 15KB in size.


Middleware

We call the primitive that returns Response as "Handler". "Middleware" is executed before and after the Handler and handles the Request and Response.

Request -> MA -> MB -> MC -> Handler returns Response -> MC -> MB -> MA -> Response

For example, we can write the middleware to add the X-Response-Time header as follows:

typescript
app.use(async (c, next) => {
    const start = Date.now()
    await next()
    const end = Date.now()
    c.res.headers.set('X-Response-Time', `${end - start}`)
    })

Hono Stacks

Hono makes easy things easy and hard things easy. It is suitable for not just only returning JSON. But it is also great for building the full-stack application including REST API servers and the client.

RPC

Hono's RPC feature allows you to share API specs with litthe change to your code. The client generated by hc will read the spec and access the endpoint type-safety.

The following libraries make it possible:


Writing API

Endpoint that receives a GET request and returns JSON

First, write an endpoint that receives a GET request and returns JSON.

typescript
import { Hono } from 'hono'

const app = new Hono()

app.get('/hello', (c) => {
  return c.json({
    message: `Hello!`,
  })
})

Validation with Zod

Validate with Zod to receive the value of the query parameter.

typescript
import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

const app = new Hono()

app.get(
  '/hello',
  zValidator(
    'query',
    z.object({
      name: z.string(),
    })
  ),
  (c) => {
    const { name } = c.req.valid('query')
    return c.json({
      message: `Hello! ${name}`,
    })
  }
)

Sharing the Types

To emit an endpoint specification, export its type.

typescript
const route = app.get(
  '/hello',
  zValidator(
    'query',
    z.object({
      name: z.string(),
    })
  ),
  (c) => {
    const { name } = c.req.valid('query')
    return c.json({
      message: `Hello! ${name}`,
    })
  }
)

export type AppType = typeof route

Released under the MIT License.