Skip to main content

Overview

This guide helps you migrate your Hono applications between major versions. Follow the instructions for your specific version upgrade.

v4.3.11 to v4.4.0

deno.land/x to JSR

There is no breaking change, but we no longer publish the module from deno.land/x. If you want to use Hono on Deno, use JSR instead. Migration:
// Before
import { Hono } from 'https://deno.land/x/hono/mod.ts'

// After
import { Hono } from 'jsr:@hono/hono'
For more details, visit: https://hono.dev/getting-started/deno

v3.12.x to v4.0.0

There are several breaking changes in v4.0.0.

Removal of Deprecated Features

The following features have been removed:

AWS Lambda Adapter

// Obsolete: LambdaFunctionUrlRequestContext
// Use: ApiGatewayRequestContextV2

Next.js Adapter

// Obsolete
import { handle } from 'hono/nextjs'

// Use Vercel adapter instead
import { handle } from 'hono/vercel'

Context Methods

import { stream, streamText } from 'hono/streaming'
import { getRuntimeKey } from 'hono/adapter'
import { getCookie } from 'hono/cookie'

// Obsolete: c.jsonT()
const res = c.json(data) // Use c.json() instead

// Obsolete: c.stream() and c.streamText()
const res = stream(c, async (stream) => {
  await stream.write('data')
})

// Obsolete: c.env()
const runtime = getRuntimeKey()

// Obsolete: req.cookie()
const value = getCookie(c, 'name')

Hono Methods

import { showRoutes, getRouterName } from 'hono/dev'

// Obsolete: app.showRoutes()
showRoutes(app)

// Obsolete: app.routerName
const name = getRouterName(app)

// Obsolete: app.head()
// app.get() now implicitly handles HEAD method
app.get('/path', handler)

// Obsolete: app.handleEvent()
// Use app.fetch() instead
app.fetch(request, env)

HonoRequest Methods

// Obsolete: req.headers(), req.body(), etc.
// Use req.raw instead
const headers = c.req.raw.headers
const body = c.req.raw.body
const bodyUsed = c.req.raw.bodyUsed

serveStatic Requires manifest

For Cloudflare Workers, specify the manifest option:
import { serveStatic } from 'hono/cloudflare-workers'
import manifest from '__STATIC_CONTENT_MANIFEST'

app.use('/static/*', serveStatic({ 
  root: './assets', 
  manifest 
}))

Other Changes

  • JSX Renderer: docType option now defaults to true
  • JSX FC: Use PropsWithChildren instead of passing children to FC
  • Mime Types: Some mime types have been removed
  • Type Changes: Improved types for middleware chaining and validation

v2.7.8 to v3.0.0

c.req is now HonoRequest

c.req is now a HonoRequest object instead of Request. Access the raw Request via c.req.raw:
app.post('/', async (c) => {
  // Before
  // const metadata = c.req.cf?.hostMetadata
  
  // After
  const metadata = c.req.raw.cf?.hostMetadata
  return c.json({ metadata })
})

StaticRouter is Obsolete

The StaticRouter has been removed. Use the default router instead.

Validator Changes

The validator API has changed:
import { validator } from 'hono/validator'

app.post(
  '/posts',
  validator('json', (value, c) => {
    // New validation API
    if (!value.title) {
      return c.text('Invalid', 400)
    }
    return value
  }),
  (c) => {
    const data = c.req.valid('json')
    return c.json(data)
  }
)

serveStatic from Adapters

serveStatic is now provided by adapters:
// For Cloudflare Workers
import { serveStatic } from 'hono/cloudflare-workers'

// For Bun
import { serveStatic } from 'hono/bun'

// For Deno
import { serveStatic } from 'npm:hono/deno'

app.get('/static/*', serveStatic({ root: './' }))

Service Worker Mode Deprecated

For Cloudflare Workers, use Module Worker mode instead:
// Before (Service Worker mode)
app.fire()

// After (Module Worker mode)
export default app

Use type for Generics

Always use type instead of interface for generics:
// Correct
type Bindings = {
  TOKEN: string
}

const app = new Hono<{ Bindings: Bindings }>()

// Incorrect
// interface Bindings {
//   TOKEN: string
// }

v2.2.5 to v2.3.0

Auth Middleware Changes

If using Basic Auth or Bearer Auth in a handler, change:
import { basicAuth } from 'hono/basic-auth'

app.use('/auth/*', async (c, next) => {
  const auth = basicAuth({ 
    username: c.env.USERNAME, 
    password: c.env.PASSWORD 
  })
  
  // Before
  // await auth(c, next)
  
  // After
  return auth(c, next)
})

v2.0.9 to v2.1.0

parseBody Changes

c.req.parseBody() now only parses FormData:
// For FormData
const data = await c.req.parseBody()

// For JSON
const jsonData = await c.req.json()

// For text
const text = await c.req.text()

// For ArrayBuffer
const arrayBuffer = await c.req.arrayBuffer()

Generics Arguments Changed

The constructor now uses Variables and Bindings:
type Bindings = {
  KV: KVNamespace
  Storage: R2Bucket
}

type Variables = {
  user: string
}

const app = new Hono<{ 
  Variables: Variables
  Bindings: Bindings 
}>()

app.get('/foo', (c) => {
  const user = c.get('user') // typed!
  const kv = c.env.KV // typed!
  return c.json({ user })
})

v1.6.4 to v2.0.0

Deno Middleware Import

Don’t import middleware from hono/mod.ts:
// Before
import { Hono, poweredBy } from 'https://deno.land/x/hono/mod.ts'

// After
import { Hono } from 'https://deno.land/x/hono/mod.ts'
import { poweredBy, basicAuth } from 'https://deno.land/x/hono/middleware.ts'
Cookie functions are now built-in:
import { getCookie, setCookie } from 'hono/cookie'

// Parse cookie
app.get('/entry/:id', (c) => {
  const value = getCookie(c, 'name')
  return c.text(value)
})

// Set cookie
app.get('/', (c) => {
  setCookie(c, 'delicious_cookie', 'choco')
  return c.text('Cookie set!')
})

Body Parse Middleware Removed

Use c.req.parseBody() instead:
// Before
import { bodyParse } from 'hono/body-parse'
app.use('*', bodyParse())

// After
app.post('/form', async (c) => {
  const body = await c.req.parseBody()
  return c.json(body)
})

GraphQL and Mustache Removed

GraphQL Server and Mustache middleware have been removed. Use third-party alternatives.

Best Practices

Always test your application thoroughly after upgrading to a new major version.
Check the official changelog for additional changes and improvements.
Update related packages like validators and middleware along with Hono.
If jumping multiple versions, upgrade one major version at a time.

Build docs developers (and LLMs) love