Hono / SonikJavaScript

HonoをVercelで動かしてみた(API / SSR HTML編)

HonoはVercelで動作すると聞いていたが、実際に試したことはなかった。Vercel向けにHonoをセットアップする方法と、Vercelでホストするためのファイルの生成方法が説明されている。Vercelにデプロイすると、Honoからのレスポンスが返ってくることが確認できた。さらに、静的HTMLの配信やHonoでSSRした結果の配信も試した。ただし、ワイルドカード(’*’)を利用する場合は注意が必要で、設定の順番によって動作が変わることがある。

広告ここから
広告ここまで

HonoがVercelで動くらしいという認識はあったのですが、実際に動かしたことがなかったので試してみました。

Vercel向けにHonoをセットアップする

create honovercelを指定すればOKです。

$ npm create hono@latest vercel-hono

create-hono version 0.3.2
✔ Using target directory … vercel-hono
? Which template do you want to use? › - Use arrow-keys. Return to submit.
  ↑ cloudflare-pages
    cloudflare-workers
    deno
    fastly
    lagon
    lambda-edge
    netlify
    nextjs
    nodejs
❯   vercel

vecel.jsonなど、Vercelでホストするためのファイルが含まれた状態で生成されてきます。

drwxrwxr-x  8 hideokamoto  staff  256 12 21 14:21 .
drwxr-xr-x  7 hideokamoto  staff  224 12 21 14:21 ..
-rw-r--r--  1 hideokamoto  staff    8 12 20 19:31 .gitignore
-rw-r--r--  1 hideokamoto  staff   34 12 20 19:31 README.md
drwxrwxr-x  3 hideokamoto  staff   96 12 21 14:21 api
-rw-r--r--  1 hideokamoto  staff  172 12 20 19:31 package.json
-rw-r--r--  1 hideokamoto  staff  186 12 20 19:31 tsconfig.json
-rw-r--r--  1 hideokamoto  staff   92 12 20 19:31 vercel.json

vercel.jsonには、Honoのアプリケーションコードが配置されているディレクトリへのrewriteルールが設定されています。

{
  "rewrites": [
    {
      "source": "/api/(.*)",
      "destination": "/api"
    }
  ]
}

そのままVercelにデプロイしてみる

GitHubにコードをpushした後、Vercelにデプロイしてみましょう。Framework PresetOtherで、特にビルド設定などは変更せずに接続します。

デプロイすると、/apiパスでちゃんとHonoからのレスポンスが返ってきます。

$ curl https://YOUR-SPACE.vercel.app/api | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    25    0    25    0     0    189      0 --:--:-- --:--:-- --:--:--   196
{
  "message": "Hello Hono!"
}

HTMLの配信も試してみる

どうせならHTMLも配信してHono + Vercelでウェブサイトやアプリを出せるようにしてみましょう。

静的HTMLだけなら、publicディレクトリに配置するだけ

SPAのランディング用かSSGなどで生成したものを配置したい場合は、publicディレクトリにHTMLを置くだけで良さそうです。public/index.htmlを追加してみました。

<!DOCTYPE html>
<html>
    <body>
        <h1>Hell static page on Vercel</h1>
    </body>
</html>

これをVercelにデプロイすると、https://YOUR-SPACE.vercel.app/にこのページが表示されます。

HonoでSSRした結果を返す

HonoでHTMLを作って配信したい場合は、vercel.jsonを少し変更します。sourceからapiを除外することで、ルートへのアクセスも/apiディレクトリにあるHonoが動くようにしました。

{
  "rewrites": [
    {
      "source": "/(.*)",
      "destination": "/api"
    },
  ]
}

あとはapi/index.tsにHTMLを返すパスを追加するだけです。

import { Hono } from 'hono'
import { handle } from 'hono/vercel'

export const config = {
  runtime: 'edge',
}

const app = new Hono()
app.get('/*', async c => {
  return c.html(`
  <!DOCTYPE html>
  <html>
      <body>
          <h1>Hell hono on Vercel</h1>
          <p>We're in the <code>${c.req.path}</code></p>
      </body>
  </html>
  `)
})

export default handle(app)

これをデプロイすると、Honoで生成したHTMLが表示されます。

publicディレクトリに配置した HTMLが優先される様子ですので、併用する場合はご注意ください。

Hono (HTML and API)を使う時の注意点

これはVercelに限った話ではなさそうですが、ワイルドカード(*)を利用する場合は、追加するタイミングを最後にしましょう。

import { Hono } from 'hono'
import { handle } from 'hono/vercel'

export const config = {
  runtime: 'edge',
}

const app = new Hono()
const apiApp = new Hono()

apiApp.get('/test', (c) => c.json({ message: 'Hello Hono!!!' }))
app.route('/api', apiApp)
app.get('/*', async c => {
  return c.html(`
  <!DOCTYPE html>
  <html>
      <body>
          <h1>Hell hono on Vercel</h1>
          <p>We're in the <code>${c.req.path}</code></p>
      </body>
  </html>
  `)
})

export default handle(app)

/*のパスを指定する前に、/apiパスを指定しています。逆にすると、/apiへのリクエストもapp.get('/*')側が動いてしまいます。

HonoにはRouteのパスマッチパターンが何種類かあったはずなので、そちらを使うことで調整できるかもしれません。が、少なくともデフォルトではこのような挙動をしますのでご注意ください。

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts