Hono / SonikJavaScript

Honoxで、サーバーサイドとクライアントサイドのfetchを試してみた

HonoでWebサイトを作る「honox」の実装方法を紹介。クライアント・サーバーサイドでのデータ取得やAPI呼び出しを説明。外部APIを用意し、クライアントでfetchやサーバーでfetch、レスポンス表示する手順を示す。Reactライクな使い勝手とHono/Cloudflare Workersっぽい特徴がある。honoxは個人的に興味深く、SSGの場合はAstroを、サーバー側処理が多い場合はhonoxを推奨。

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

HonoでWebサイトを作れる「honox」が登場しました。サイト構築となると、外部のAPIからデータを取得する処理を書くことが少なくないですが、honoxでクライアントサイド・サーバーサイドそれぞれどのように実装することになるかを試してみた覚書です。

プロジェクトのセットアップ

テストに使うプロジェクトを、create-honoで作りましょう。

% npm create hono
Need to install the following packages:
  create-hono@0.4.0
Ok to proceed? (y) 

honoxを使うには、テンプレートでx-basicを指定します。

? Which template do you want to use? › - Use arrow-keys. Return to submit.
  ↑ cloudflare-pages
    cloudflare-workers
    deno
    fastly
    lambda-edge
    netlify
    nextjs
    nodejs
    vercel
❯   x-basic

そのほかの設定は好みに任せて行いましょう。最後に次のような生成完了メッセージが出ればOKです。

cloned honojs/starter#main to /Users/sandbox
✔ Copied project files

呼び出すAPIを用意する

外部APIを呼び出すテストですので、APIをまずは用意しましょう。honoxはhonoをベースにしていますので、APIの作成も簡単です。app/server.tsに次のようなコードを追加します。

import { showRoutes } from 'hono/dev'
import { createApp } from 'honox/server'

const app = createApp()

app.get('/api', async c => {
    return c.json({
        message: 'hello'
    })
})

showRoutes(app)


export default app

これで/apiに対するGETリクエストを処理できるようになりました。

クライアント側でのfetchを試みる

まずはクライアント側での呼び出しを試してみましょう。テンプレートにあるapp/islands/counter.tsxを次のように変更します。

import { useState } from 'hono/jsx'

export default function Counter() {
  const [message, setMessage] = useState("")
  return (
    <div>
      <p>{message}</p>
      <button onClick={async () => {
        const result = await fetch('/api')
        const data = await result.json<{message: string}>()
        setMessage(data.message)
      }}>Fetch</button>
    </div>
  )
}

ボタンクリック時のイベントでfetchを行い、useStateで値をコンポーネントに渡しています。

Reactライクにかけるのが便利ですね。

サーバー側でのfetchにトライする

続いてサーバー側の処理も試してみましょう。今度はapp/routes/index.tsxを編集します。

import { css } from 'hono/css'
import { createRoute } from 'honox/factory'
import Counter from '../islands/counter'

const className = css`
  font-family: sans-serif;
`

export default createRoute(async (c) => {
  const name = c.req.query('name') ?? 'Hono'
  const result = await fetch(`${c.req.url}api`)
  const {message} = await result.json<{message: string}>()
  return c.render(
    <div class={className}>
      <h1>Hello, {name}!</h1>
      <h2>{message}</h2>
      <Counter />
    </div>,
    { title: name }
  )
})

c.renderに渡す値を、await fetchで取得しています。「Hello, 」の後ろ部分がAPIレスポンスになっていますので、次のような表示になるはずです。

やってみての感想

Reactっぽさもありつつ、Hono / Cloudflare Workersっぽい書き方もできるので、個人的にはhonoxはなかなか面白いなと思っています。Astroとかも使い勝手がよいなと思いますが、サーバー側の処理(コンポーネント・API)が多めのサイトやアプリについてはこちらで、どちらかというとSSG的な用途で使いたい場合はAstroかなぁというイメージですね。

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

WP Kyotoサポーター募集中

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

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

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

Related Category posts