Revolutionizing Backend Development: Hono and Bun Unleashed
Written on
Chapter 1: Introduction to Hono and Bun
As I explored the capabilities of Bun, I became intrigued by the fresh frameworks emerging within its ecosystem. While Express.js has served us well over the years, it feels somewhat outdated given the evolution of JavaScript and its libraries. So, what alternatives do we have? Enter Hono—a promising new framework worth examining.
Creating Your First Hono Project
To kick off our project, we need to establish a directory for it and run bun init. Here’s the essential code for our initial setup. You can utilize Postman for making requests.
Bun.serve({
fetch() {
return new Response("Hello from Bun");},
port: process.env.PORT || 3000,
});
We can execute the application with bun run index.ts.
Adding Hono to Your Project
Next, let’s integrate Hono into our application. First, install Hono with:
bun install hono
Then, create an instance of the app and replace our placeholder response with app.fetch.
import { Hono } from "hono";
const app = new Hono();
Bun.serve({
fetch: app.fetch, // new
port: process.env.PORT || 3000,
});
Enabling Watch Mode
To streamline development, we can leverage watch mode to automatically restart the server when changes are made:
bun --watch index.ts
Creating Your First Route
In this setup, we utilize context instead of traditional request and response parameters. To send JSON responses, simply use the context.json() method:
app.get("/users", (context) => {
return context.json({ userCount: 10 });
});
Testing the Users Endpoint
Currently, we aren't logging any output to the console upon hitting endpoints, which is less than ideal. Fortunately, Hono provides built-in middleware such as logger, CORS, and basicAuth, and you can also craft custom middleware.
import { Hono } from "hono";
import { logger } from "hono/logger"; // new
const app = new Hono();
app.use("*", logger()); // new
app.get("/users", (context) => {
return context.json({ userCount: 10 });
});
Bun.serve({
fetch: app.fetch,
port: process.env.PORT || 3000,
});
Utilizing JSX for Templating
Hono allows you to use JSX as a template engine. To get started, update your tsconfig.json file:
{
"compilerOptions": {
"lib": ["ESNext"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx"
// ... other config settings ...
}
}
Then, create a file named page.tsx in your root directory and add your JSX content:
import type { FC } from 'hono/jsx';
const Layout: FC = (props) => {
return (
<div>
{props.children}</div>
);
};
const Page: FC<{ messages: string[] }> = (props: { messages: string[] }) => {
return (
<Layout>
<h1>Hello Hono!</h1>
{props.messages.map((message) => {
return <p>{message}!</p>;})}
</Layout>
);
};
export default Page;
Rename index.ts to index.tsx to utilize JSX, and run the app with bun-watch index.tsx.
import { Hono } from "hono";
import { logger } from "hono/logger";
import Page from "./page.tsx"; // new
const app = new Hono();
app.use("*", logger());
app.get("/", (context) => { // new
const messages = ["Orange", "Apple", "Banana"];
return context.html(<Page messages={messages} />);
});
app.get("/users", (context) => {
return context.json({ userCount: 10 });
});
Bun.serve({
fetch: app.fetch,
port: process.env.PORT || 3000,
});
Now, our content should render correctly on the webpage.
Validation Layer Implementation
It's crucial to implement a validation layer since we cannot control user inputs from the frontend. We can use Zod for this purpose:
bun add zod
bun add @hono/zod-validator
Create an endpoint that incorporates validation. Specify in zValidator whether to use JSON or form data and define the validation schema:
import { Hono } from "hono";
import { logger } from "hono/logger";
import Page from "./page.tsx";
import { zValidator } from "@hono/zod-validator"; // new
import { z } from "zod"; // new
const app = new Hono();
app.use("*", logger());
app.post("/users", zValidator( // new
"json",
z.object({
firstName: z.string(),
lastName: z.string(),
})
), (context) => context.json("ok"));
Testing with Valid and Invalid Data
First, let’s validate with appropriate data. Everything should function as expected. Now, let’s try with invalid data to see the error handling in action.
Conclusion: Why Hono is a Worthy Contender
Hono shares many similarities with Express.js. If you're accustomed to Express, transitioning to Hono could be seamless. It's always beneficial to have multiple options available.
If you found this content insightful, consider following us for more updates and resources as we continue our learning journey together. Your thoughts and comments are always appreciated!
In Plain English 🚀
Thank you for being part of the In Plain English community! Before you leave, don't forget to:
- Clap and follow the author! 👏
- Connect with us on X | LinkedIn | YouTube | Discord | Newsletter
- Explore our other platforms: Stackademic | CoFeed | Venture | Cubed
- Discover more content at PlainEnglish.io
Chapter 2: Hono in Action
To further grasp the functionalities of Hono and Bun, check out this informative video:
The React, Bun & Hono Tutorial 2024 - Drizzle, Kinde, Tanstack, Tailwind, TypeScript, RPC, & more - YouTube provides a comprehensive look at these technologies.
And here's another video that discusses why some developers are moving away from Express.js in favor of Bun and Hono:
I Stopped Using Express.js: Because Bun and Hono - YouTube highlights the advantages of adopting these modern frameworks.