Honoに入門してみる

## はじめに

Cloudflare Workersやネットの技術記事で、定期的にhonoを見るようになりました。
せっかくなので、Honoのチュートリアルを触ってみます。

https://hono.dev/


## スターターテンプレートでプロダクトを作成します

```sh
$ npm create hono@latest my-app
```

cloudflare-workersを利用します。

```sh
? Which template do you want to use?
    aws-lambda
    bun
    cloudflare-pages
❯   cloudflare-workers
    deno
    fastly
    lagon
    nextjs
    nodejs
    vercel
```

プロダクトが作成されたら、プロダクトのディレクトリへ移動して、`npm i`します。

```sh
$ cd my-app
$ npm i
```

下記のようなディレクトリ構成が展開されています。

```sh
.
├── README.md
├── node_modules
├── package-lock.json
├── package.json
├── src
│   └── index.ts
├── tsconfig.json
└── wrangler.toml
```

`npm i`が終わったら、下記のコマンドでローカルサーバーを立ち上げます。

```sh
$ npm run dev

> dev
> wrangler dev src/index.ts

 ⛅️ wrangler 3.22.1
-------------------
⎔ Starting local server...
[wrangler:inf] Ready on http://localhost:1234
[wrangler:inf] GET / 200 OK (33ms)
[wrangler:inf] GET /favicon.ico 404 Not Found (8ms)
```

表示されるlocalhostへアクセスすると、下記のようにHello Hono!が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3589058/e603bc26-f6c2-3965-d158-c349fb606025.png)


## JSONを返す処理の実装

GET リクエストを処理し、レスポンスを返す例です。

```js:
import { Hono } from 'hono'

const app = new Hono()

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

```

`http://localhost:1234/api/hello` へアクセスすると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3589058/928ff90b-d127-989f-da7b-987ceaacacd6.png)

## リクエストとレスポンスの実装

パス パラメーター、URL クエリ値を取得し、Response ヘッダーを追加する手順は次のように記述されます。


```js
app.get('/posts/:id', (c) => {
  const page = c.req.query('page')
  const id = c.req.param('id')
  c.header('X-Message', 'Hi!')
  return c.text(`You want see ${page} of ${id}`)
})
```

`http://localhost:1234/posts/123?page=1`などにアクセスすると、下記のように渡した値に合わせて表示が返ってきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3589058/b499c5bc-5a80-e07e-04e9-012b92447ac4.png)


## HTMLを返す

`src/index.ts`を`src/index.tsx`に変更します。

```tsx:src/index.tsx
import { Hono } from 'hono'

const app = new Hono()

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

app.get('/page', (c) => {
  return c.html(<View />)
})
export default app

```

ファイル名の変更に合わせて`package.json`の`scripts`で、`index.ts`を指定している箇所を`index.tsx`に修正します。


```json
{
  "scripts": {
    "dev": "wrangler dev src/index.tsx",
    "deploy": "wrangler deploy --minify src/index.tsx"
  },
```

上記の変更を終えたら、`$ npm run dev`し直し、`localhost:1234/page`にアクセスすると、HTMLが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3589058/c543879e-b10a-8b0d-1698-62204fb73b18.png)


## 生のResponseを返す実装

[Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)を返すこともできます。

```ts
app.get('/', (c) => {
  return new Response('Good morning!')
})
```


## Middlewareの実装

チュートリアルでは、Basic認証の例です。
Firebase Auth などの外部ライブラリを使用したサードパーティのミドルウェアも提供されているとのことで、便利にログイン処理の実装ができそうです。

```ts
import { Hono } from 'hono'
import { basicAuth } from 'hono/basic-auth'


const app = new Hono()

app.use(
  '/admin/*',
  basicAuth({
    username: 'admin',
    password: 'secret',
  })
)

app.get('/admin', (c) => {
  return c.text('Your are authorized!')
})

export default app
```

実際にアクセスするとBasic認証が可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3589058/4106736b-3d47-7b68-e7a5-336e69b8a512.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3589058/83507941-b75d-90a4-4ab7-a672a3540fcd.png)



## 終わりに

とりあえず、Honoのチュートリアルを走ってみました。
CloudflareWorkerを個人開発に使いだしているのですが、Workers+JSだけだと面倒な部分をHonoが良い感じに吸収してくれそうです。次のプロダクトではHonoを使ってみようかな？と思います。