DenoでHonoを試すメモ


DenoのWebフレームワークを調べていて色々なフレームワークが出てくるのですが、Deno Deploy向けという形でベンダーロックインされそうな雰囲気があったのでDenoだけでなく他の場所でも動くようなフレームワークが無いか探してたらHonoというフレームワークがありました。

Cloudflare WorkersやBunでも動くということでちょっと触ってみました。

触ってみた感覚としては、ルーティング周りなどExpressっぽい書き味でNode.js Expressを触ったことがある人なら直感的に書けるような印象です。

全然関係ないですが、スプラトゥーンのフェスでほのおを選んだタイミングだったので謎のシンパシーを感じて勢いで触ってみています。

> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/f736048e-3b7f-a541-8024-56f6c64e4115.png" width="300px" />

## HonoをDenoで動かす

Honoのサイトにチュートリアルがあります。

https://honojs.dev/docs/getting-started/deno/

こちらのサンプルコードを使うとそのまま動きました。

```server.ts
import { serve } from 'https://deno.land/std/http/server.ts'
import { Hono } from 'https://deno.land/x/hono/mod.ts'

const app = new Hono()

app.get('/', (c) => c.text('Hello! Hono!'))

serve(app.fetch)
```

`app.get('/')`のあたりの書き方はexpressっぽい書き方で個人的には馴染みがあって好きです。

```bash
$ deno run --allow-net server.ts
```

ライトに始められていいですね。

## HTMLなどの静的ファイルを配信する

[こちら](https://honojs.dev/docs/builtin-middleware/serve-static/)のドキュメントを参考に、`static`フォルダを作成し、`index.html`など適当なhtmlファイルを設置します。

> ![スクリーンショット 2022-12-11 19.36.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/2511b545-33f0-abac-077d-501c17022399.png "スクリーンショット 2022-12-11 19.36.02.png")

Denoの場合静的ファイルの読み込みに

> import { serveStatic } from 'https://deno.land/x/hono/middleware.ts'

この読み込みが必要なようです。

また`app.use()`を指定して静的ファイルを設置するフォルダを指定するのもexpress風だなと感じました。

> app.use('/static/*', serveStatic({ root: './' }))

以下のような感じでHTMLで作成したファイルが表示されます。


```server.ts
import { serve } from 'https://deno.land/std/http/server.ts'
import { Hono } from 'https://deno.land/x/hono/mod.ts'
import { serveStatic } from 'https://deno.land/x/hono/middleware.ts'

const app = new Hono()

app.use('/static/*', serveStatic({ root: './' }))
app.use('/favicon.ico', serveStatic({ path: './favicon.ico' }))
app.get('/', serveStatic({ path: './static/index.html' }))

serve(app.fetch)
```

`--allow-read`を追加

```bash
$ deno run --allow-net --allow-read server.ts
```

### 画像やCSSを当ててみる

こちらのサンプルがフォルダ構成など参考になります。

> https://github.com/honojs/examples/tree/main/serve-static

staticフォルダ内に

- index.html
- style.css
- test.png

を直下に置いてます。

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="/static/style.css">
</head>
<body>
    <h1>こんばんわ</h1>
    <img src="/static/test.png" alt="Dinotocat" />
</body>
</html>
```

```style.css
h1{
    color: red;
}
```

```server.ts
import { serve } from 'https://deno.land/std/http/server.ts'
import { Hono } from 'https://deno.land/x/hono/mod.ts'

import { serveStatic } from 'https://deno.land/x/hono/middleware.ts'

const app = new Hono()

app.use('/static/*', serveStatic({ root: './' }))
app.use('/favicon.ico', serveStatic({ path: './favicon.ico' }))
app.get('/', serveStatic({ path: './static/index.html' }))

app.get('/hello', (c) => c.text('Hello! Hono!'))

serve(app.fetch)
```

`/`にアクセスするとindex.htmlの内容が表示され、cssや画像も表示されました。

`/hello`にアクセスするとそのままテキストで`Hello! Hono!`が表示されます。

> ![](https://i.gyazo.com/a3897f04fd32893e528b4a077293ab21.png)

## APIサーバーを作る

こちらのドキュメントを参考にJSONを返すAPIを作れそうです。

> https://honojs.dev/docs/builtin-middleware/pretty-json/

prettyJSONのモジュールを追加して簡単なコードで書ける模様です。

> import { prettyJSON } from 'https://deno.land/x/hono/middleware.ts'

```server.ts
const app = new Hono()

app.use('*', prettyJSON()) // With options: prettyJSON({ space: 4 })
app.get('/', (c) => {
  return c.json({ message: 'Hono!' })
})
```

簡単にAPIサーバーが立ち上がりました。

> ![スクリーンショット 2022-11-06 17.12.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/3b3d9ac2-6551-409e-f885-e38368dff9ae.png "スクリーンショット 2022-11-06 17.12.14.png")


postを受けたければ`app.post()`でいけそうですね。

## URLパラメーターを取得する

`app.get('/hoge/:name'`という形式でURLのパラメーターから値を取得できます。



```server.ts
app.get('/qiita/:item_id', (c) => {
  const item_id = c.req.param('item_id');

  return c.json({
    item_id: item_id,
    message: `Hello Hono API`,
  })
})
```

## 外部APIにリクエストするAPIを作る

説明[WIP]

```server.ts
app.get('/qiita/:item_id', async (c) => {

  const item_id = c.req.param('item_id');
  const res = await getQiita(item_id);

  return c.json({
    item_id: item_id,
    message: `Hello Hono API`,
    body: res
  })
})
```

> ![](https://i.gyazo.com/c7922501d3f2ad8461939d78c67fcbb6.png)