DenoのWebフレームワークを調べていて色々なフレームワークが出てくるのですが、Deno Deploy向けという形でベンダーロックインされそうな雰囲気があったのでDenoだけでなく他の場所でも動くようなフレームワークが無いか探してたらHonoというフレームワークがありました。
Cloudflare WorkersやBunでも動くということでちょっと触ってみました。
触ってみた感覚としては、ルーティング周りなどExpressっぽい書き味でNode.js Expressを触ったことがある人なら直感的に書けるような印象です。
全然関係ないですが、スプラトゥーンのフェスでほのおを選んだタイミングだったので謎のシンパシーを感じて勢いで触ってみています。
HonoをDenoで動かす
Honoのサイトにチュートリアルがあります。
こちらのサンプルコードを使うとそのまま動きました。
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っぽい書き方で個人的には馴染みがあって好きです。
$ deno run --allow-net server.ts
ライトに始められていいですね。
HTMLなどの静的ファイルを配信する
こちらのドキュメントを参考に、static
フォルダを作成し、index.html
など適当なhtmlファイルを設置します。
Denoの場合静的ファイルの読み込みに
import { serveStatic } from 'https://deno.land/x/hono/middleware.ts'
この読み込みが必要なようです。
またapp.use()
を指定して静的ファイルを設置するフォルダを指定するのもexpress風だなと感じました。
app.use('/static/*', serveStatic({ root: './' }))
以下のような感じでHTMLで作成したファイルが表示されます。
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
を追加
$ deno run --allow-net --allow-read server.ts
画像やCSSを当ててみる
こちらのサンプルがフォルダ構成など参考になります。
staticフォルダ内に
- index.html
- style.css
- test.png
を直下に置いてます。
<!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>
h1{
color: red;
}
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!
が表示されます。
APIサーバーを作る
こちらのドキュメントを参考にJSONを返すAPIを作れそうです。
prettyJSONのモジュールを追加して簡単なコードで書ける模様です。
import { prettyJSON } from 'https://deno.land/x/hono/middleware.ts'
const app = new Hono()
app.use('*', prettyJSON()) // With options: prettyJSON({ space: 4 })
app.get('/', (c) => {
return c.json({ message: 'Hono!' })
})
簡単にAPIサーバーが立ち上がりました。
postを受けたければapp.post()
でいけそうですね。
URLパラメーターを取得する
app.get('/hoge/:name'
という形式でURLのパラメーターから値を取得できます。
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]
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
})
})