Hono — Ultra-Fast Web Framework Guide
Advertisement
Hono is a new-generation framework designed for Edge Computing. It's tiny, fast, and works everywhere — Cloudflare Workers, Bun, Deno, and Node.js.
What is Hono?
Hono is built for the future of computing:
- Ultra-lightweight: 14KB minified
- Edge-ready: Runs on Cloudflare Workers
- Multi-platform: Deno, Bun, Node.js, browsers
- TypeScript first: Excellent type inference
npm create hono@latest my-app
cd my-app
npm run dev
Basic Server
import { Hono } from "hono";
const app = new Hono();
app.get("/", (c) => c.text("Hello, World!"));
app.post("/users", async (c) => {
const user = await c.req.json();
return c.json({ id: 1, ...user }, 201);
});
export default app;
- What is Hono?
- Basic Server
- Routing
- Middleware
- Handlers and Contexts
- Error Handling
- Type Safety
- Deployment Targets
- Cloudflare Workers
- Bun
- Deno
- Node.js
- Advanced Features
- Form Data
- File Serving
- OpenAPI/Swagger Integration
- Comparison: Hono vs Express vs Fastify
- FAQ
Routing
const app = new Hono();
// Basic routes
app.get("/", (c) => c.text("GET"));
app.post("/", (c) => c.text("POST"));
app.put("/", (c) => c.text("PUT"));
app.delete("/", (c) => c.text("DELETE"));
// Path parameters
app.get("/users/:id", (c) => {
const id = c.req.param("id");
return c.json({ id });
});
// Query parameters
app.get("/search", (c) => {
const q = c.req.query("q");
return c.json({ query: q });
});
// Regex routes
app.get(/^\/posts\/.+$/, (c) => c.text("Post"));
// Groups
const api = new Hono();
api.get("/users", (c) => c.json([]));
app.route("/api", api);
Middleware
import { Hono } from "hono";
import { logger } from "hono/logger";
import { cors } from "hono/cors";
import { bearerAuth } from "hono/bearer-auth";
const app = new Hono();
// Logging
app.use(logger());
// CORS
app.use(cors());
// Authentication
app.use("/api/*", bearerAuth({ token: "secret" }));
// Custom middleware
app.use(async (c, next) => {
console.log(`${c.req.method} ${c.req.path}`);
await next();
});
app.get("/api/protected", (c) => c.json({ data: "secret" }));
export default app;
Handlers and Contexts
const app = new Hono();
// Context object (c) provides access to request and response
app.post("/users", async (c) => {
// Request
const body = await c.req.json();
const headers = c.req.headers();
const path = c.req.path;
const url = c.req.url;
// Response
return c.json(
{ id: 1, ...body },
{
status: 201,
headers: { "X-Custom": "Header" },
}
);
});
// Type-safe params and queries
interface Params {
id: string;
}
app.get("/users/:id", (c) => {
const { id } = c.req.param();
const limit = c.req.query("limit");
return c.json({ id, limit });
});
Error Handling
import { HTTPException } from "hono/http-exception";
const app = new Hono();
app.get("/users/:id", async (c) => {
const id = c.req.param("id");
const user = await getUser(parseInt(id));
if (!user) {
throw new HTTPException(404, { message: "User not found" });
}
return c.json(user);
});
// Global error handler
app.onError((err, c) => {
console.error(err);
return c.json({ error: "Internal Server Error" }, 500);
});
Type Safety
interface User {
id: number;
name: string;
email: string;
}
interface CreateUserInput {
name: string;
email: string;
}
const app = new Hono<{
Bindings: {
DB: D1Database; // Cloudflare D1
CACHE: KVNamespace; // Cloudflare KV
};
}>();
app.post("/users", async (c) => {
const input = (await c.req.json()) as CreateUserInput;
const db = c.env.DB;
const result = await db.prepare("INSERT INTO users (name, email) VALUES (?, ?)").bind(input.name, input.email).run();
return c.json({ id: result.meta.last_row_id, ...input }, 201);
});
Deployment Targets
Cloudflare Workers
import { Hono } from "hono";
const app = new Hono();
app.get("/", (c) => c.text("Hello from Cloudflare!"));
export default app;
npm install wrangler
wrangler deploy
Bun
bunx create-hono my-app
cd my-app
bun dev
Deno
import { Hono } from "https://deno.land/x/hono/mod.ts";
const app = new Hono();
app.get("/", (c) => c.text("Hello from Deno!"));
Deno.serve(app.fetch);
Node.js
import { Hono } from "hono";
import { serve } from "@hono/node-server";
const app = new Hono();
app.get("/", (c) => c.text("Hello from Node.js!"));
serve({
fetch: app.fetch,
port: 3000,
});
Advanced Features
Form Data
app.post("/upload", async (c) => {
const form = await c.req.parseFormData();
const file = form.get("file");
const name = form.get("name");
return c.json({ uploaded: true, name });
});
File Serving
app.get("/static/:path", serveStatic({ root: "./public" }));
OpenAPI/Swagger Integration
import { openapi } from "@hono/zod-openapi";
const app = openapi();
app.openapi(
openapi.registry().registerComponent("schemas", "User", {
type: "object",
properties: {
id: { type: "number" },
name: { type: "string" },
},
})
);
Comparison: Hono vs Express vs Fastify
| Feature | Express | Fastify | Hono |
|---|---|---|---|
| Size | 50KB | 32KB | 14KB |
| Edge Ready | No | No | Yes |
| Cloudflare Workers | No | No | Yes |
| Type Safety | Limited | Good | Excellent |
| Performance | Good | Excellent | Excellent |
FAQ
Q: Should I use Hono for traditional Node.js servers? A: It works, but Express/Fastify are more mature. Use Hono if Edge deployment is your goal.
Q: Is Hono production-ready? A: Yes, many companies use it in production on Cloudflare Workers.
Q: Can I use Hono with databases? A: Yes, works with any database. Cloudflare D1 is native integration.
Hono is the future of lightweight web frameworks. Perfect for Edge Computing and serverless, it's also great for small APIs and microservices anywhere.
Advertisement