Back

Conseils pour porter une application Express vers Hono

Conseils pour porter une application Express vers Hono

Si vous maintenez une API Express et envisagez une migration vers Hono, la première chose à comprendre est qu’il ne s’agit pas d’une migration par simple rechercher-remplacer. Express est bâti sur le module http de Node et utilise ses propres objets req/res. Hono, lui, repose sur la Fetch API et les standards du Web. Cette différence influence tout : le routage, les middlewares, le traitement des requêtes et les réponses.

Voici ce qu’il faut savoir avant de se lancer.

Points clés à retenir

  • Express et Hono reposent sur des fondations fondamentalement différentes : le module http de Node d’un côté, la Fetch API et les standards du Web de l’autre.
  • Hono remplace les objets distincts req et res d’Express par un unique objet de contexte c, et les handlers doivent retourner une Response.
  • Les signatures des middlewares diffèrent — Express utilise (req, res, next) tandis que Hono utilise (c, next) avec un next() attendu via await.
  • Le parsing du corps des requêtes se fait directement dans les handlers Hono, plutôt qu’à travers un middleware global.
  • Une migration incrémentale, en commençant par les routes JSON sans état, est bien plus sûre qu’une réécriture complète.

Comprendre d’abord la différence architecturale

Express encapsule les objets IncomingMessage et ServerResponse de Node. Chaque objet req et res est spécifique à Node. Hono, en revanche, fonctionne avec les objets standards Request et Response — les mêmes que ceux que vous utiliseriez dans un navigateur ou un Cloudflare Worker.

Lorsque vous exécutez Hono sur Node.js, vous utilisez l’adaptateur @hono/node-server, qui fait le pont. Mais le handler lui-même reste agnostique vis-à-vis du 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)
})

La forme est similaire, mais c (l’objet de contexte) remplace à la fois req et res. Vous retournez une Response au lieu d’appeler des méthodes sur res.

Migrer des API Node.js vers Hono : commencez par les routes sans état

L’endroit le plus sûr pour commencer à porter des applications Express vers Hono, ce sont les routes sans état, exclusivement JSON — pas d’accès au système de fichiers, pas de streams spécifiques à Node, pas de middleware de session. Celles-ci se traduisent proprement.

Les routes qui dépendent d’API spécifiques à Node (req.socket, res.locals, res.sendFile) demandent davantage de réflexion. Isolez-les en premier afin de savoir à quoi vous avez affaire avant de vous engager dans une migration complète.

Migration des middlewares Hono : ne présumez pas de la compatibilité

Les middlewares Express suivent le modèle (req, res, next). Les middlewares Hono utilisent (c, next) et appellent généralement await next(). Ils ne sont pas interchangeables.

// Express middleware
app.use((req, res, next) => {
  req.startTime = Date.now()
  next()
})

// Hono equivalent
app.use(async (c, next) => {
  c.set('startTime', Date.now())
  await next()
})

Pour les paquets courants, Hono propose des équivalents officiels :

ExpressÉquivalent Hono
cors()hono/cors
helmet()hono/secure-headers
express.json()Intégré via c.req.json()
morganhono/logger ou un middleware personnalisé

Réécrivez les middlewares de manière intentionnelle plutôt que d’essayer d’encapsuler ceux d’Express — l’abstraction tient rarement proprement.

Traitement du corps des requêtes et des réponses

Dans Express 5, le parsing du corps reste basé sur un middleware. Dans Hono, vous parsez le corps directement dans le handler :

// Hono body parsing
app.post('/items', async (c) => {
  const body = await c.req.json()
  return c.json({ received: body }, 201)
})

Les réponses sont toujours retournées, jamais mutées. Il n’y a pas de res.status(201).json(...) — à la place, vous passez le statut comme second argument à c.json().

Gestion des erreurs

Express utilise un gestionnaire d’erreurs à quatre arguments (err, req, res, next). Hono utilise app.onError :

app.onError((err, c) => {
  console.error(err)
  return c.json({ error: 'Internal Server Error' }, 500)
})

Migrez de manière incrémentale, pas d’un seul coup

Une réécriture complète se passe rarement sans accroc. Une meilleure approche :

  1. Portez un groupe de routes isolé à la fois.
  2. Faites tourner Hono en parallèle d’Express durant la transition.
  3. Réécrivez les middlewares explicitement — ne les encapsulez pas.
  4. Gardez les dépendances spécifiques à Node (gestion de fichiers, authentification héritée) pour la fin.

Conclusion

Porter des applications Express vers Hono est simple une fois que l’on accepte que les deux frameworks reposent sur des fondations différentes. La syntaxe de routage est suffisamment familière pour que la plupart des routes se traduisent en quelques minutes. Le vrai travail réside dans les middlewares et tout ce qui touche directement aux API spécifiques à Node. Abordez ces points de manière réfléchie, et la migration deviendra gérable.

FAQ

Oui. Un schéma courant consiste à placer un reverse proxy ou un petit point d'entrée Node devant les deux, en routant des chemins spécifiques vers l'application Hono et en laissant le reste à Express. Cela vous permet de migrer les groupes de routes un par un et de revenir en arrière rapidement en cas de problème, plutôt que de vous engager dans une bascule unique et risquée.

Hono fonctionne sur Node.js, Bun, Deno, Cloudflare Workers, AWS Lambda et plusieurs autres runtimes. Sur Node, vous utilisez l'adaptateur @hono/node-server pour faire le pont entre le modèle Fetch API et le module http de Node. Le même code de handler reste portable d'un runtime à l'autre, ce qui constitue l'un des principaux avantages de Hono par rapport à Express.

En général, non. Les middlewares Express dépendent des objets req et res de Node et de la callback next, tandis que les middlewares Hono opèrent sur un contexte de style Fetch. Quelques adaptateurs communautaires existent, mais ils ont tendance à être fragiles. L'approche recommandée est de réécrire les middlewares en utilisant l'API de Hono, étant donné que la plupart des besoins courants disposent déjà d'équivalents officiels ou intégrés.

Hono est généralement plus rapide qu'Express, en particulier pour le routage et les réponses JSON, grâce à son routeur léger et à sa conception basée sur Fetch. Les gains réels dépendent de votre charge de travail — les requêtes en base de données et les appels externes sont généralement prédominants. Considérez la performance comme un effet secondaire bénéfique de la migration, et non comme la raison principale, à moins que vos benchmarks ne montrent que la surcharge du routage constitue un véritable goulot d'étranglement.

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.

OpenReplay