Dicas para Portar uma Aplicação Express para o Hono
Se você mantém uma API Express e está considerando migrar para o Hono, a primeira coisa que vale a pena entender é que esta não é uma migração de “localizar e substituir”. O Express é construído sobre o módulo http do Node e seus próprios objetos req/res. O Hono é construído sobre a Fetch API e os Web Standards. Essa diferença molda tudo: roteamento, middleware, tratamento de requisições e respostas.
Aqui está o que você precisa saber antes de começar.
Principais Conclusões
- Express e Hono se apoiam em fundamentos fundamentalmente diferentes: o módulo
httpdo Node versus a Fetch API e os Web Standards. - O Hono substitui os objetos separados
reqeresdo Express por um único objeto de contextoc, e os handlers precisam retornar umResponse. - As assinaturas de middleware diferem — o Express usa
(req, res, next)enquanto o Hono usa(c, next)com umnext()aguardado via await. - O parsing do corpo da requisição acontece diretamente dentro dos handlers do Hono, em vez de através de middleware global.
- Uma migração incremental, começando com rotas JSON sem estado, é muito mais segura do que uma reescrita completa.
Entenda Primeiro a Diferença Arquitetural
O Express encapsula o IncomingMessage e o ServerResponse do Node. Cada objeto req e res é específico do Node. O Hono, em contraste, trabalha com objetos Request e Response padrão — os mesmos que você usaria em um navegador ou em um Cloudflare Worker.
Ao rodar o Hono no Node.js, você usa o adaptador @hono/node-server, que faz a ponte entre os dois mundos. Mas o handler em si permanece agnóstico em relação ao runtime.
// Express
app.get('/users/:id', async (req, res) => {
const user = await db.findById(req.params.id)
res.json(user)
})
// Hono
app.get('/users/:id', async (c) => {
const user = await db.findById(c.req.param('id'))
return c.json(user)
})
O formato é semelhante, mas c (o objeto de contexto) substitui tanto req quanto res. Você retorna um Response em vez de chamar métodos em res.
Migrando APIs Node.js para o Hono: Comece com Rotas Sem Estado
O lugar mais seguro para começar a portar aplicações Express para o Hono é com rotas sem estado, apenas JSON — sem acesso ao sistema de arquivos, sem streams específicos do Node, sem middleware de sessão. Essas se traduzem de forma limpa.
Rotas que dependem de APIs específicas do Node (req.socket, res.locals, res.sendFile) exigem mais reflexão. Isole-as primeiro, para saber com o que está lidando antes de se comprometer com uma migração completa.
Discover how at OpenReplay.com.
Migração de Middleware no Hono: Não Assuma Compatibilidade
O middleware do Express segue o padrão (req, res, next). O middleware do Hono usa (c, next) e tipicamente chama await next(). Eles não são intercambiáveis.
// Middleware Express
app.use((req, res, next) => {
req.startTime = Date.now()
next()
})
// Equivalente Hono
app.use(async (c, next) => {
c.set('startTime', Date.now())
await next()
})
Para pacotes comuns, o Hono tem equivalentes oficiais:
| Express | Equivalente Hono |
|---|---|
cors() | hono/cors |
helmet() | hono/secure-headers |
express.json() | Embutido via c.req.json() |
morgan | hono/logger ou um middleware customizado |
Reescreva o middleware de forma intencional, em vez de tentar encapsular o middleware do Express — a abstração raramente se mantém de forma limpa.
Tratamento do Corpo da Requisição e Resposta
No Express 5, o parsing do corpo ainda é baseado em middleware. No Hono, você faz o parsing do corpo diretamente no handler:
// Parsing do corpo no Hono
app.post('/items', async (c) => {
const body = await c.req.json()
return c.json({ received: body }, 201)
})
As respostas são sempre retornadas, nunca mutadas. Não há res.status(201).json(...) — em vez disso, você passa o status como segundo argumento para c.json().
Tratamento de Erros
O Express usa um manipulador de erros com quatro argumentos (err, req, res, next). O Hono usa app.onError:
app.onError((err, c) => {
console.error(err)
return c.json({ error: 'Internal Server Error' }, 500)
})
Migre de Forma Incremental, Não Tudo de Uma Vez
Uma reescrita completa raramente corre bem. Uma abordagem melhor:
- Porte um grupo de rotas isolado de cada vez.
- Execute o Hono junto com o Express durante a transição.
- Reescreva o middleware explicitamente — não o encapsule.
- Deixe dependências específicas do Node (manipulação de arquivos, autenticação legada) por último.
Conclusão
Portar aplicações Express para o Hono é simples, uma vez que você aceite que os dois frameworks se apoiam em fundamentos diferentes. A sintaxe de roteamento é familiar o suficiente para que a maioria das rotas se traduza em minutos. O trabalho real está no middleware e em qualquer coisa que toque diretamente em APIs específicas do Node. Aborde essas partes com cuidado, e a migração se torna gerenciável.
FAQs
Sim. Um padrão comum é colocar um proxy reverso ou um pequeno ponto de entrada Node na frente de ambos, roteando caminhos específicos para a aplicação Hono e deixando o restante com o Express. Isso permite migrar grupos de rotas um de cada vez e fazer rollback rapidamente se algo quebrar, em vez de se comprometer com uma única transição arriscada.
O Hono roda no Node.js, Bun, Deno, Cloudflare Workers, AWS Lambda e vários outros runtimes. No Node, você usa o adaptador @hono/node-server para fazer a ponte entre o modelo da Fetch API e o módulo http do Node. O mesmo código de handler permanece portátil entre runtimes, o que é uma das principais vantagens do Hono sobre o Express.
Geralmente, não. O middleware do Express depende dos objetos req e res do Node e do callback next, enquanto o middleware do Hono opera em um contexto no estilo Fetch. Existem alguns adaptadores da comunidade, mas tendem a ser frágeis. A abordagem recomendada é reescrever o middleware contra a API do Hono, já que a maioria das necessidades comuns já tem equivalentes oficiais ou embutidos.
O Hono é geralmente mais rápido que o Express, particularmente para roteamento e respostas JSON, graças ao seu roteador leve e design baseado em Fetch. Os ganhos no mundo real dependem da sua carga de trabalho — consultas a banco de dados e chamadas externas geralmente dominam. Trate o desempenho como um efeito colateral útil da migração, não como o motivo principal, a menos que seus benchmarks mostrem que o overhead de roteamento é um gargalo real.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.