Советы по переносу Express-приложения на Hono
Если вы поддерживаете API на Express и рассматриваете переход на Hono, первое, что стоит понять: это не миграция через «найти и заменить». Express построен на модуле http из Node и собственных объектах req/res. Hono построен на Fetch API и веб-стандартах. Это различие определяет всё: маршрутизацию, middleware, обработку запросов и ответов.
Вот что нужно знать перед началом.
Ключевые выводы
- Express и Hono базируются на принципиально разных основах: модуль
httpиз Node против Fetch API и веб-стандартов. - Hono заменяет раздельные объекты
reqиresиз Express единым объектом контекстаc, а обработчики должны возвращатьResponse. - Сигнатуры middleware различаются — Express использует
(req, res, next), тогда как Hono использует(c, next)с awaited-вызовомnext(). - Парсинг тела запроса выполняется непосредственно внутри обработчиков Hono, а не через глобальный middleware.
- Постепенная миграция, начиная со stateless JSON-маршрутов, гораздо безопаснее, чем полное переписывание.
Сначала разберитесь в архитектурных различиях
Express оборачивает объекты IncomingMessage и ServerResponse из Node. Каждый объект req и res специфичен для Node. Hono, напротив, работает со стандартными объектами Request и Response — теми же, которые вы использовали бы в браузере или Cloudflare Worker.
При запуске Hono на Node.js вы используете адаптер @hono/node-server, который устраняет этот разрыв. Но сам обработчик остаётся независимым от 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)
})
Форма похожа, но c (объект контекста) заменяет одновременно req и res. Вы возвращаете Response, а не вызываете методы на res.
Миграция Node.js API на Hono: начните со stateless-маршрутов
Самое безопасное место для начала переноса Express-приложений на Hono — это stateless-маршруты, работающие только с JSON: без обращения к файловой системе, без специфичных для Node потоков, без session middleware. Они переводятся чисто.
Маршруты, зависящие от специфичных для Node API (req.socket, res.locals, res.sendFile), требуют более продуманного подхода. Изолируйте их в первую очередь, чтобы понимать, с чем имеете дело, прежде чем решаться на полную миграцию.
Discover how at OpenReplay.com.
Миграция middleware в Hono: не предполагайте совместимость
Middleware в Express следует шаблону (req, res, next). Middleware в Hono использует (c, next) и обычно вызывает await next(). Они не взаимозаменяемы.
// Express middleware
app.use((req, res, next) => {
req.startTime = Date.now()
next()
})
// Эквивалент в Hono
app.use(async (c, next) => {
c.set('startTime', Date.now())
await next()
})
Для распространённых пакетов у Hono есть официальные эквиваленты:
| Express | Эквивалент в Hono |
|---|---|
cors() | hono/cors |
helmet() | hono/secure-headers |
express.json() | Встроено через c.req.json() |
morgan | hono/logger или кастомный middleware |
Переписывайте middleware осознанно, а не пытайтесь оборачивать Express middleware — такая абстракция редко работает чисто.
Обработка тела запроса и ответа
В Express 5 парсинг тела по-прежнему основан на middleware. В Hono вы парсите тело непосредственно в обработчике:
// Парсинг тела в Hono
app.post('/items', async (c) => {
const body = await c.req.json()
return c.json({ received: body }, 201)
})
Ответы всегда возвращаются, а не мутируются. Здесь нет res.status(201).json(...) — вместо этого вы передаёте статус вторым аргументом в c.json().
Обработка ошибок
Express использует обработчик ошибок с четырьмя аргументами (err, req, res, next). Hono использует app.onError:
app.onError((err, c) => {
console.error(err)
return c.json({ error: 'Internal Server Error' }, 500)
})
Мигрируйте постепенно, а не всё сразу
Полное переписывание редко проходит гладко. Лучший подход:
- Переносите одну изолированную группу маршрутов за раз.
- Запускайте Hono параллельно с Express в период перехода.
- Переписывайте middleware явно — не оборачивайте его.
- Оставьте Node-специфичные зависимости (работа с файлами, устаревшая аутентификация) на потом.
Заключение
Перенос Express-приложений на Hono несложен, как только вы примете, что эти два фреймворка стоят на разных основах. Синтаксис маршрутизации достаточно знаком, чтобы большинство маршрутов переводилось за минуты. Настоящая работа кроется в middleware и во всём, что напрямую обращается к Node-специфичным API. Подходите к этому продуманно — и миграция станет управляемой.
Часто задаваемые вопросы
Да. Распространённый паттерн — поставить обратный прокси или небольшую точку входа на Node перед обоими, направляя определённые пути в Hono-приложение и оставляя остальное на Express. Это позволяет мигрировать группы маршрутов поочерёдно и быстро откатываться при поломке, вместо того чтобы решаться на единственный рискованный переход.
Hono работает на Node.js, Bun, Deno, Cloudflare Workers, AWS Lambda и нескольких других runtime. На Node вы используете адаптер @hono/node-server, чтобы соединить модель Fetch API с модулем http из Node. Один и тот же код обработчиков остаётся переносимым между runtime — это одно из главных преимуществ Hono перед Express.
В целом — нет. Express middleware зависит от объектов req и res из Node и колбэка next, тогда как middleware Hono работает с контекстом в стиле Fetch. Существуют некоторые community-адаптеры, но они, как правило, ненадёжны. Рекомендуемый подход — переписывать middleware под API Hono, поскольку для большинства распространённых задач уже есть официальные или встроенные эквиваленты.
Hono в целом быстрее Express, особенно при маршрутизации и формировании JSON-ответов, благодаря лёгкому роутеру и дизайну на основе Fetch. Реальный прирост зависит от вашей нагрузки — обычно доминируют запросы к БД и внешним сервисам. Воспринимайте производительность как полезный побочный эффект миграции, а не как основную причину, если только ваши бенчмарки не показывают, что накладные расходы маршрутизации — реальное узкое место.
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.