ExpressJS VS HonoJS

16 min. read |
Article

As a MERN Stack developer, I've always appreciated the minimalist approach of the Express framework. It has been my go-to for setting up a web server, even for minor server functionalities. But recently, I found myself at a crossroads. The diverse JavaScript ecosystem

The Express Journey

Our messed up Diverse Ecosystem of JavaScript offers a plethora of backend frameworks, each with its own strengths and quirks. NestJS, Fastify, Koa, and even NextJS (if you consider it a backend framework) are all compelling options.


As a beginner, I naturally gravitated towards ExpressJS — the tried-and-true choice.

However, as I matured in my development journey, I began to notice its limitations. Express hadn't fully embraced modern web standards like some of its counterparts. NextJS and Astro, for instance, stood out with their better developer experiences and serverless deployment capabilities.

Oh, and Typescript just works out of the box🤩.

Enter Hono

Amidst this dilemma, I stumbled upon a short video by Ben Holmes. It mentioned Hono - a modern backend framework that promised speed, lightweight design, adherence to web standards, and compatibility with any JavaScript runtime. But what really caught my attention? Hono’s router outpaced all the other frameworks I’d considered.

Enough Story Time—Let’s Code!

Now let’s roll up our sleeves and build something. How about a tasks manager app to track your New Year resolutions.

The app should include:

  • Authentication and Authorization
  • MongoDB for storing our tasks
  • CRUD functionality for our tasks

We’ll build with both Express and Hono and evaluate the pros and cons of both on the basis of:

  • Developer Experience
  • Performance
  • Bundle Size
  • Flexibility

1. App Structure

Code Snippet

The above file structure should be familiar to you if you’ve used Express before. The index.ts file is the entry point of our server. We have the same Model View Controller architecture along with an auth middleware for protected routes. We are using Typescript (obviously 🤷‍♂️) so we have defined some files for the reusability of our interfaces and enums. One additional advantage with Hono is that it comes with Typescript by default. In Express you have to configure it yourself.

Hono can be configured with multiple deployment/server options, I’m currently using the NodeJS server adapter in this demo but you can use whichever deployment option fits your needs.

2. Router

One notable difference is that Hono doesn’t allow abstracting away the callback function of a route in a separate controller file. But fear not! As your codebase grows, you can always create utility functions to encapsulate specific business logic.

Now, let’s compare how we’d fetch a list of tasks for a user using Express and Hono.

The below code is in our tasks.router.ts file

The actual business logic will be written in a separate controller file tasks.controller.ts


Hono is much more like the API endpoints of NextJS Instead of abstracting the business logic into a new controller file, the Hono docs recommend that we write all the code related to a particular route right there in the tasks.router.ts file so that Typescript can properly infer the types.

In the above code Snippet, the router works similarly to express where you import your Router in your index.ts file const app = new Hono() and app.route("/api/tasks", tasks);. you also receive a context object in the callback function, which lets you access the request headers, query params, form data, JSON body etc. and also lets you return JSON, Plain Text, HTML and even JSX as a response. It’s pretty neat.

3. Lightweight yet Batteries Included

If you’ve used Express before, you have to set up middleware for even the basic stuff required for a good server. This can be a good thing for experienced devs as it gives them more control to pick or not to pick a certain package but can be confusing for beginners.

You have to install separate packages for setting up cors, form submissions, file uploads, secure headers, JSON web tokens, session cookies etc.

While Hono has everything a good backend framework needs, it has built-in middleware for everything above.

Let’s take a look at the index.ts files in both scenarios

Express

Hono


As you can see, Hono takes care of everything from having a built-in logger, handling cors and adding security headers while in Express you have to install separate packages like morgan, cors, helmet to achieve the same functionality.

Now I know that these are not large packages and don’t affect the bundle size but if I was a beginner developer and a framework took care of these small yet important things without me having to figure it out on my own, I’ll be more productive doing the actual coding.

4. Validations and Middleware

Hono is also better at handling server-side request validations

In Express, we usually define the validation schema in a separate .validator.ts file with the express-validator package and return a custom message in response to our .controller.ts if the body doesn’t pass our validation schema.

In our Hono app, we use zod to handle validations, you can use any other package but I prefer Zod because I love it it integrates very nicely with the @hono/zod-validator package of Hono.

In Hono, we don’t need to manually send the response, you only need to add the validation middleware and when you’re done, hono will automatically handle the rest. Isn’t it cool!


Middleware

Hono has built-in middleware for handling both cookie or jwt-based authentication. We used the JWT implementation in our app below but you can also check out cookie-based auth in Hpno

In Hono, you can just import the JWT package and sign and verify the JWT token very easily without relying on any third party libraries.

In the code below, we are signing the token with the user._id property.


Then in our middleware function, we can verify the token and if it’s valid, we set the user on the context object of the hono router and access the user object in any of our routes if we are authenticated.

The protect middleware is largely similar to middleware in an Express app. In Express, when we extract the token from the request headers, we validate it using the jwt.verify() method and assign our user object to res.locals.user. Later in our controllers, we access it similarly.

Production Ready?

After evaluating both apps based on the criteria discussed in this section, I believe we can confidently tick off all the items below:

  • Excellent Developer Experience (especially with TypeScript 😍)
  • Exceptionally performant Router (faster than Express)
  • Significantly smaller bundle size (thanks to the built-in middleware)
  • Extremely flexible (deployable on any runtime)
Sure, that’s impressive, but can it handle a large scale production app?

Well, that’s entirely up to you. It can perform every function that Express does, strictly adheres to modern web standards, supports all major runtimes, and is extremely potent for handling concurrent requests. So, why not give it a shot?

If you’re considering migrating your Express app to Hono, I assure you it won’t cause much trouble.

I strongly recommend giving this a try.

Until Next Time,

Happy Debugging Coding👋

Back To Articles