הונו הוא כל מה שרציתי מ express

02/09/2024

הונו (hono) הוא ספרייה לפיתוח ווב שקצת מזכירה את אקספרס אבל על סטרואידים - יש לו תמיכה מלאה בכל סביבת הרצת JavaScript, תמיכה מובנית בבדיקות, טייפסקריפט ישר מהקופסה, הוא יותר מהיר וגם מגיע עם ספריית צד-לקוח שמזכירה את ריאקט אבל הרבה יותר קטנה. הנה שלוש דוגמאות מהירות כדי להתרשם ממנו.

1. פיתוח פרויקט חדש

כל מה שצריך בשביל לפתוח פרויקט hono חדש זה את דינו מותקן ולהריץ את הפקודה:

deno run -A npm:create-hono@latest my-app

אני בוחר את דינו בתור סביבת הריצה וזה הכל. עכשיו אפשר להפעיל VS Code בתיקייה ולהתחיל לעבוד.

הדבר הראשון שאני רוצה לשנות בהגדרות הפרויקט יהיה בקובץ deno.json וזה להוסיף לתבנית משימה של פיתוח שתעבוד במצב watch. אני מעדכן את הקובץ ואחרי השינוי הוא נראה כך:

{
  "imports": {
    "hono": "jsr:@hono/hono@^4.5.10"
  },
  "tasks": {
    "start": "deno run --allow-net main.ts",
    "dev": "deno run --allow-net --watch main.ts"
  },
  "compilerOptions": {
    "jsx": "precompile",
    "jsxImportSource": "hono/jsx"
  },
  "deploy": {
    "project": "b737e735-3715-4077-a44b-782fc7424cb5",
    "exclude": [
      "**/node_modules"
    ],
    "include": [],
    "entrypoint": "main.ts"
  }
}

השורה היחידה שהוספתי היא הערך dev בתוך האוביקט tasks.

משורת הפקודה אני מפעיל:

deno task dev

ויש לי שרת שמקשיב על פורט 8000 ואני יכול להתחיל לעבוד, הקוד כתוב בטייפסקריפט וכל שינוי קוד אוטומטית מרענן את השרת.

2. דוגמה 1 - החזרת מידע

אני יוצר תיקיה חדשה בשם routes ובתוכה קובץ בשם demo1.ts עם התוכן הבא:

import { Hono } from "hono";

const router = new Hono();
let counter = 0;

router.get('/text', (c) => {
  return c.text('Hello Hono!')
})

router.get('/api/hello', (c) => {
  return c.json({
    ok: true,
    message: 'Hello Hono!',
  })
})

router.get('/api/counter', (c) => {
  return c.json({
    value: counter++,
  })
})

export default router;

הקובץ מגדיר שלושה נתיבים, אחד מחזיר טקסט, השני והשלישי מחזירים אוביקטי JSON. בשביל לגשת לנתיבים אני צריך לחבר אותם לשרת ולכן אני הולך לקובץ main.ts ושם מעדכן את הקובץ לתוכן הבא:

import { Hono } from 'hono'
import demo1 from './routes/demo1.ts';

const app = new Hono()
app.route('demo1', demo1);

Deno.serve(app.fetch)

עכשיו בדפדפן אני גולש ל localhost:8000/demo1/text כדי לראות את הטקסט, ל localhost:8000/demo1/api/hello כדי לראות את האוביקט הראשון ול localhost:8000/demo1/api/counter כדי לראות את האוביקט השני.

3. דוגמה 2 - גישה לפרמטרים של הבקשה

בואו נפתח קובץ נוסף בשם routes/demo2.ts והפעם עם התוכן הבא:

import { Hono } from "hono";

const router = new Hono();

router.get('hello', (c) => {
  const name = c.req.query('name') ?? 'Guest';
  return c.text(`Hello! ${name}`);
});

router.post('item', async (c) => {
  const props = await c.req.json();
  console.log(props);
  return c.json(props);
})

export default router;

הקובץ מגדיר שני נתיבים - נתיב אחד לוקח את הפרמטר name מה Query String ומחזיר טקסט שכולל את הערך של הפרמטר או שם ברירת מחדל. הנתיב השני לוקח את גוף הבקשה בתור אוביקט JSON ומחזיר אותו. בשביל לחבר אותם לאפליקציה צריך רק להוסיף את השורה:

app.route('demo2', demo2);

לקובץ main.ts, וכן אפילו לא צריך לסגור ולפתוח את התוכנית הכל פשוט מתרענן ומראה את הנתיבים המעודכנים.

4. דוגמה 3 - שליחת HTML

הקובץ השלישי שלנו נקרא routes/demo3.tsx, וכן הסיומת היא tsx ולא ts הפעם. זה התוכן שלו:

import { Hono } from "hono";

const router = new Hono();

const View = ({name = "Guest"}) => {
  return (
    <html>
      <body>
        <h1>Hello! {name}</h1>
      </body>
    </html>
  )
}

router.get('/', (c) => {
  return c.html(<View name="ynon" />)
})

export default router;

אתם לא טועים - זה נראה כמו JSX וזה אכן זה. ל Hono יש דרך מובנית ופשוטה לכתוב HTML באמצעות jsx. יש שם עוד כל מיני קיצורים גם ל CSS ואפילו ספריית JavaScriptשהולכת עם זה ומאפשרת להוסיף תמיכה ב Hooks כמו useEffect, אבל זה כבר סיפור לפוסט אחר.

5. בדיקות אוטומטיות

הונו משתלב עם מנגנון הבדיקות האוטומטיות של דינו בצורה מובנית. ניצור תיקייה בשם tests ובתוכה קובץ בשם tests/demo1_test.ts עם התוכן הבא:

import { expect } from "jsr:@std/expect";
import demo1 from '../routes/demo1.ts';

// basic test
Deno.test("simple test", async () => {
  const res = await demo1.request('/text')
  expect(res.status).toBe(200)
  expect(await res.text()).toBe('Hello Hono!')
});

אפשר להפעיל את הבדיקה עם:

$ deno test

או בלחיצה על אייקון ההרצה המשולש ליד קוד הבדיקה שיופיע אוטומטית ב VS Code.

6. העלאה לרשת

וכמובן בגלל שזה דינו יש לנו העלאה אוטומטית לרשת בחינם ב denodeploy. צריך רק לכתוב:

deployctl deploy

משורת הפקודה ולעקוב אחר ההוראות. הפרויקט שלי זמין כבר בקישור:

https://ynonp-hono-demo.deno.dev/demo1/api/hello

ואתם מוזמנים לעבור על הקוד המלא בגיטהאב בקישור:

https://github.com/ynonp/hono-demo

סך הכל העבודה עם הונו היתה כל מה ש Express היה פעם - כיף, עובד בלי כאב ראש ועושה כל מה שצריך.