برسوں تک JavaScript ویب فریم ورک منتخب کرنا مطلب ٹریڈ آف قبول کرنا تھا: Express عالمگیر مگر سست اور Node سے بندھا، Fastify تیز مگر صرف Node کے لیے، Next.js مکمل مگر بھاری۔ جب ایج رن ٹائم — Cloudflare Workers، Deno Deploy، Bun، Vercel Edge — آئے، ان فریم ورکس کی حدود ظاہر ہوئیں۔
Hono (جاپانی میں "شعلہ" 🔥) جدید جواب ہے۔ 14KB سے کم کا فریم ورک، مکمل طور پر ویب اسٹینڈرڈز (Request، Response، fetch) پر بنا ہوا، ہر JavaScript رن ٹائم پر چلتا ہے۔ ایک ہی کوڈ Cloudflare Workers، Bun، Deno، Node.js، Vercel، Netlify اور AWS Lambda پر بغیر تبدیلی کے ڈپلائے ہوتا ہے۔
Hono کیوں
- پرفارمنس۔
RegExpRouterتمام روٹ پیٹرن کو ایک regex میں کمپائل کرتا ہے، روایتی روٹرز کے لینیئر لوپس سے بچتا ہے۔ بینچ مارکس 4 لاکھ ops/s سے زیادہ ہیں۔ - پورٹیبلٹی۔ ویب اسٹینڈرڈز یعنی Node پر صفر انحصار۔ ایک ہی
app.fetchCloudflare Worker میں default export،Bun.serveکو پاس، Deno سرور پر ماؤنٹ یا@hono/node-serverکے ساتھ اڈیپٹ ہوتا ہے۔ - TypeScript فرسٹ DX۔ لٹرل ٹائپس کے طور پر اخذ شدہ پاتھ پیرامیٹرز، اینڈ ٹو اینڈ ٹائپ سیف RPC کلائنٹ۔
شروع کرنا
npm create hono@latest my-api cd my-api npm install npm run dev
اسٹارٹر پوچھتا ہے کونسا ٹیمپلیٹ: cloudflare-workers، bun، deno، nodejs، vercel، aws-lambda، nextjs وغیرہ۔ تیز آزمائش کے لیے ایک فائل سے بھی شروع کر سکتے ہیں:
// src/index.ts import { Hono } from 'hono' const app = new Hono() app.get('/', (c) => c.text('Hello Hono!')) export default app
Cloudflare Workers پر یہ کافی ہے۔ Bun پر: Bun.serve({ fetch: app.fetch, port: 3000 })۔ Node پر: @hono/node-server سے serve({ fetch: app.fetch })۔
روٹنگ
import { Hono } from 'hono' const app = new Hono() app.get('/', (c) => c.text('Home')) app.get('/posts/:id', (c) => { const id = c.req.param('id') return c.json({ id }) }) app.get('/posts/:id/comments/:commentId', (c) => { const { id, commentId } = c.req.param() return c.json({ id, commentId }) }) app.get('/files/*', (c) => c.text('Wildcard')) app.post('/posts', async (c) => { const body = await c.req.json() return c.json({ created: body }, 201) })
روٹس گروپ کرنا
// routes/posts.ts import { Hono } from 'hono' const posts = new Hono() posts.get('/', (c) => c.json({ posts: [] })) posts.get('/:id', (c) => c.json({ id: c.req.param('id') })) export default posts // src/index.ts import { Hono } from 'hono' import posts from './routes/posts' const app = new Hono() app.route('/posts', posts)
Context آبجیکٹ
app.post('/echo', async (c) => { const userAgent = c.req.header('User-Agent') const page = c.req.query('page') const body = await c.req.json() const env = c.env c.set('requestId', crypto.randomUUID()) const id = c.get('requestId') c.header('X-Request-Id', id) c.status(200) return c.json({ userAgent, page, body, id }) })
مڈل ویئر: اونیئن ماڈل
import { Hono } from 'hono' import { logger } from 'hono/logger' import { cors } from 'hono/cors' import { secureHeaders } from 'hono/secure-headers' const app = new Hono() app.use('*', logger()) app.use('*', secureHeaders()) app.use('/api/*', cors({ origin: 'https://spinny.dev' })) app.use('*', async (c, next) => { const start = performance.now() await next() c.header('X-Response-Time', `${performance.now() - start}ms`) })
بلٹ ان مڈل ویئر
| مڈل ویئر | کام |
|---|---|
logger | میتھڈ، پاتھ، اسٹیٹس، دورانیہ کی منظم لاگ |
cors | origin، میتھڈز، ہیڈرز کے مطابق قابلِ ترتیب CORS |
csrf | origin پر مبنی CSRF تحفظ |
secureHeaders | CSP، HSTS، X-Frame-Options سیٹ کرتا ہے |
bearerAuth / basicAuth | فوری Bearer/Basic auth |
jwt | jose سے JWT تصدیق/دستخط |
etag | ETag پیدا کرتا ہے، 304 ہینڈل کرتا ہے |
cache | Web Cache API کیشنگ |
compress | جواب پر gzip/deflate |
bodyLimit | حد سے اوپر باڈی مسترد |
timing | پروفائلنگ کے لیے Server-Timing ہیڈر |
ٹائپ سیف کسٹم مڈل ویئر
import { createMiddleware } from 'hono/factory' type AuthVars = { userId: string; role: 'user' | 'admin' } export const requireAuth = createMiddleware<{ Variables: AuthVars }>( async (c, next) => { const token = c.req.header('Authorization')?.replace('Bearer ', '') if (!token) return c.json({ error: 'Unauthorized' }, 401) const payload = await verifyJwt(token) c.set('userId', payload.sub) c.set('role', payload.role) await next() } ) app.get('/me', requireAuth, (c) => { const userId = c.var.userId return c.json({ userId }) })
Zod کے ساتھ ویلیڈیشن
import { Hono } from 'hono' import { zValidator } from '@hono/zod-validator' import { z } from 'zod' const createPost = z.object({ title: z.string().min(1).max(200), body: z.string().min(1), tags: z.array(z.string()).default([]), }) app.post( '/posts', zValidator('json', createPost), (c) => { const data = c.req.valid('json') return c.json({ ok: true, post: data }, 201) } )
RPC: اینڈ ٹو اینڈ ٹائپ سیف کلائنٹ
// server.ts import { Hono } from 'hono' import { zValidator } from '@hono/zod-validator' import { z } from 'zod' const app = new Hono() .get('/posts/:id', (c) => c.json({ id: c.req.param('id'), title: 'Hello' }) ) .post( '/posts', zValidator('json', z.object({ title: z.string(), body: z.string() })), (c) => c.json({ ok: true }, 201) ) export type AppType = typeof app export default app
// client.ts import { hc } from 'hono/client' import type { AppType } from './server' const client = hc<AppType>('https://api.spinny.dev') const res = await client.posts[':id'].$get({ param: { id: '42' } }) if (res.ok) { const data = await res.json() console.log(data.title) } const created = await client.posts.$post({ json: { title: 'سلام', body: 'Hono ایک شعلہ ہے' }, })
اسٹیٹس کوڈ تفریق
.get('/posts/:id', (c) => { const post = findPost(c.req.param('id')) if (!post) return c.json({ error: 'not found' }, 404) return c.json({ post }, 200) })
const res = await client.posts[':id'].$get({ param: { id } }) if (res.status === 404) { const { error } = await res.json() } if (res.status === 200) { const { post } = await res.json() }
روٹرز اور پرفارمنس
| روٹر | طاقتیں | کب استعمال کریں |
|---|---|---|
RegExpRouter | اعلی ترین رفتار، کمپائلڈ regex | زیادہ تر APIs کے لیے ڈیفالٹ |
TrieRouter | ہر پیٹرن سپورٹ | پیچیدہ پیٹرن جنہیں RegExp ہینڈل نہیں کرتا |
SmartRouter | بہترین خود کار طریقے سے منتخب | تجویز کردہ ڈیفالٹ |
LinearRouter | الٹرا فاسٹ رجسٹریشن | ون شاٹ ورکر، اہم کولڈ سٹارٹ |
PatternRouter | کم سے کم بنڈل (<15KB) | انتہائی سائز پابندیاں |
import { Hono } from 'hono' import { LinearRouter } from 'hono/router/linear-router' const app = new Hono({ router: new LinearRouter() })
ملٹی رن ٹائم ڈپلائے
Cloudflare Workers
import { Hono } from 'hono' type Bindings = { MY_KV: KVNamespace; DB: D1Database } const app = new Hono<{ Bindings: Bindings }>() app.get('/cache/:key', async (c) => { const value = await c.env.MY_KV.get(c.req.param('key')) return c.json({ value }) }) export default app
ڈپلائے: npx wrangler deploy۔
Bun
import { Hono } from 'hono' const app = new Hono() app.get('/', (c) => c.text('Bun + Hono')) Bun.serve({ fetch: app.fetch, port: 3000 })
Node.js
import { serve } from '@hono/node-server' import { Hono } from 'hono' const app = new Hono() app.get('/', (c) => c.text('Node + Hono')) serve({ fetch: app.fetch, port: 3000 })
Deno
import { Hono } from 'jsr:@hono/hono' const app = new Hono() app.get('/', (c) => c.text('Deno + Hono')) Deno.serve(app.fetch)
Vercel
// api/[[...route]].ts import { Hono } from 'hono' import { handle } from 'hono/vercel' const app = new Hono().basePath('/api') app.get('/hello', (c) => c.json({ msg: 'Hello from Vercel' })) export const GET = handle(app) export const POST = handle(app)
عملی مثال: auth اور DB کے ساتھ REST API
import { Hono } from 'hono' import { jwt } from 'hono/jwt' import { logger } from 'hono/logger' import { cors } from 'hono/cors' import { zValidator } from '@hono/zod-validator' import { z } from 'zod' type Bindings = { DB: D1Database; JWT_SECRET: string } type Variables = { jwtPayload: { sub: string } } const app = new Hono<{ Bindings: Bindings; Variables: Variables }>() app.use('*', logger()) app.use('/api/*', cors({ origin: 'https://spinny.dev', credentials: true })) const auth = (c: any, next: any) => jwt({ secret: c.env.JWT_SECRET })(c, next) const api = app.basePath('/api') api.get('/posts', async (c) => { const { results } = await c.env.DB .prepare('SELECT id, title, created_at FROM posts ORDER BY created_at DESC LIMIT 50') .all() return c.json({ posts: results }) }) api.post( '/posts', auth, zValidator('json', z.object({ title: z.string().min(1).max(200), body: z.string().min(1), })), async (c) => { const { title, body } = c.req.valid('json') const userId = c.var.jwtPayload.sub const result = await c.env.DB .prepare('INSERT INTO posts (title, body, author_id) VALUES (?, ?, ?) RETURNING id') .bind(title, body, userId) .first<{ id: number }>() return c.json({ id: result?.id }, 201) } ) api.onError((err, c) => { console.error(err) return c.json({ error: 'Internal error' }, 500) }) export type AppType = typeof api export default app
ٹیسٹنگ
import { describe, it, expect } from 'vitest' import app from '../src/index' describe('GET /api/posts', () => { it('پوسٹس کی فہرست واپس کرتا ہے', async () => { const res = await app.request('/api/posts') expect(res.status).toBe(200) const body = await res.json() expect(body.posts).toBeInstanceOf(Array) }) })
بہترین مشقیں
1. روٹ ڈیفینیشنز کو چین کریں
const app = new Hono() .get('/posts', handler1) .post('/posts', handler2) .get('/posts/:id', handler3)
2. عمل درآمد نہیں، ٹائپ ایکسپورٹ کریں
کلائنٹ کو AppType امپورٹ کرنا چاہیے۔
3. ہر ڈومین فی روٹر
posts، users، webhooks کے لیے سب ایپ۔
4. سرحد پر ہمیشہ ویلیڈیٹ کریں
ہر بیرونی ان پٹ zValidator سے گزرے۔
5. گلوبل کلائنٹس نہیں، بائنڈنگز پر انحصار کریں
Cloudflare پر c.env کے ذریعے KV/D1/R2 رسائی۔
6. روٹر کو بہتر بنانے سے پہلے پیمائش کریں
ڈیفالٹ SmartRouter 95٪ کیسز میں ٹھیک ہے۔
نتیجہ
Hono 2026 میں TypeScript میں ایج ریڈی APIs بنانے کا ڈی فیکٹو معیار بن گیا ہے۔
شروع کرنے کی چیک لسٹ:
npm create hono@latestاور اپنا رن ٹائم ٹیمپلیٹ منتخب کریں- چینگ سے روٹس ڈیفائن کریں (
.get(...).post(...))logger،cors،secureHeadersکو گلوبل مڈل ویئر کے طور پر شامل کریں- ہر ان پٹ کو
@hono/zod-validatorسے ویلیڈیٹ کریںAppTypeایکسپورٹ کریں اور ٹائپ سیفhcکلائنٹ سے API استعمال کریںapp.request()سے ٹیسٹ لکھیں — HTTP سرور کی ضرورت نہیںwrangler deploy(CF)،vercel deployیا اپنے رن ٹائم کے بنڈلر سے ڈپلائے کریں