コンテンツへスキップ

Cloudflare Pages

Cloudflare Pagesは、フルスタックWebアプリケーションのためのエッジプラットフォームです。静的ファイルと、Cloudflare Workersによって提供される動的コンテンツを提供します。

HonoはCloudflare Pagesを完全にサポートしています。これにより、快適な開発者体験がもたらされます。Viteの開発サーバーは高速で、Wranglerを使用したデプロイは非常に迅速です。

1. セットアップ

Cloudflare Pagesのスターターが利用可能です。「create-hono」コマンドでプロジェクトを開始してください。この例では、cloudflare-pagesテンプレートを選択してください。

sh
npm create hono@latest my-app
sh
yarn create hono my-app
sh
pnpm create hono my-app
sh
bunx create-hono my-app
sh
deno run -A npm:create-hono my-app

my-appに移動し、依存関係をインストールします。

sh
cd my-app
npm i
sh
cd my-app
yarn
sh
cd my-app
pnpm i
sh
cd my-app
bun i

以下は基本的なディレクトリ構造です。

テキスト
./
├── package.json
├── public
│   └── static // Put your static files.
│       └── style.css // You can refer to it as `/static/style.css`.
├── src
│   ├── index.tsx // The entry point for server-side.
│   └── renderer.tsx
├── tsconfig.json
└── vite.config.ts

2. Hello World

src/index.tsxを以下のように編集します

tsx
import { Hono } from 'hono'
import { renderer } from './renderer'

const app = new Hono()

app.get('*', renderer)

app.get('/', (c) => {
  return c.render(<h1>Hello, Cloudflare Pages!</h1>)
})

export default app

3. 実行

ローカルで開発サーバーを実行します。次に、Webブラウザでhttp://localhost:5173にアクセスします。

sh
npm run dev
sh
yarn dev
sh
pnpm dev
sh
bun run dev

4. デプロイ

Cloudflareアカウントをお持ちの場合は、Cloudflareにデプロイできます。package.jsonで、$npm_execpathを任意のパッケージマネージャーに変更する必要があります。

sh
npm run deploy
sh
yarn deploy
sh
pnpm run deploy
sh
bun run deploy

GitHubを使用してCloudflareダッシュボード経由でデプロイ

  1. Cloudflareダッシュボードにログインし、アカウントを選択します。
  2. アカウントホームで、Workers & Pages > アプリケーションの作成 > Pages > Gitに接続 を選択します。
  3. GitHubアカウントを認証し、リポジトリを選択します。ビルドとデプロイの設定で、以下の情報を提供します。
設定オプション
本番ブランチmain
ビルドコマンドnpm run build
ビルドディレクトリdist

バインディング

変数、KV、D1などのCloudflareバインディングを使用できます。このセクションでは、変数とKVを使用してみましょう。

wrangler.tomlを作成

最初に、ローカルバインディング用のwrangler.tomlを作成します

sh
touch wrangler.toml

wrangler.tomlを編集します。MY_NAMEという名前の変数を指定します。

toml
[vars]
MY_NAME = "Hono"

KVを作成

次に、KVを作成します。次のwranglerコマンドを実行します

sh
wrangler kv namespace create MY_KV --preview

次の出力として、preview_idをメモします。

{ binding = "MY_KV", preview_id = "abcdef" }

preview_idをバインディングの名前MY_KVで指定します

toml
[[kv_namespaces]]
binding = "MY_KV"
id = "abcdef"

vite.config.tsを編集

vite.config.tsを編集します

ts
import devServer from '@hono/vite-dev-server'
import adapter from '@hono/vite-dev-server/cloudflare'
import build from '@hono/vite-cloudflare-pages'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
    devServer({
      entry: 'src/index.tsx',
      adapter, // Cloudflare Adapter
    }),
    build(),
  ],
})

アプリケーションでバインディングを使用

アプリケーションで変数とKVを使用します。型を設定します。

ts
type Bindings = {
  MY_NAME: string
  MY_KV: KVNamespace
}

const app = new Hono<{ Bindings: Bindings }>()

それらを使用します

tsx
app.get('/', async (c) => {
  await c.env.MY_KV.put('name', c.env.MY_NAME)
  const name = await c.env.MY_KV.get('name')
  return c.render(<h1>Hello! {name}</h1>)
})

本番環境では

Cloudflare Pagesでは、ローカル開発にはwrangler.tomlを使用しますが、本番環境ではダッシュボードでバインディングを設定します。

クライアント側

Viteの機能を使用して、クライアント側のスクリプトを作成し、アプリケーションにインポートできます。/src/client.tsがクライアントのエントリーポイントの場合、スクリプトタグに記述するだけです。さらに、import.meta.env.PRODは、開発サーバーで実行しているか、ビルドフェーズで実行しているかを検出するのに役立ちます。

tsx
app.get('/', (c) => {
  return c.html(
    <html>
      <head>
        {import.meta.env.PROD ? (
          <script type='module' src='/static/client.js'></script>
        ) : (
          <script type='module' src='/src/client.ts'></script>
        )}
      </head>
      <body>
        <h1>Hello</h1>
      </body>
    </html>
  )
})

スクリプトを適切にビルドするには、以下に示す例の構成ファイルvite.config.tsを使用できます。

ts
import pages from '@hono/vite-cloudflare-pages'
import devServer from '@hono/vite-dev-server'
import { defineConfig } from 'vite'

export default defineConfig(({ mode }) => {
  if (mode === 'client') {
    return {
      build: {
        rollupOptions: {
          input: './src/client.ts',
          output: {
            entryFileNames: 'static/client.js',
          },
        },
      },
    }
  } else {
    return {
      plugins: [
        pages(),
        devServer({
          entry: 'src/index.tsx',
        }),
      ],
    }
  }
})

次のコマンドを実行して、サーバーとクライアントのスクリプトをビルドできます。

sh
vite build --mode client && vite build

Cloudflare Pagesミドルウェア

Cloudflare Pagesは、Honoのミドルウェアとは異なる独自のミドルウェアシステムを使用します。_middleware.tsという名前のファイルでonRequestをエクスポートすることで有効にできます。次のようになります。

ts
// functions/_middleware.ts
export async function onRequest(pagesContext) {
  console.log(`You are accessing ${pagesContext.request.url}`)
  return await pagesContext.next()
}

handleMiddlewareを使用すると、HonoのミドルウェアをCloudflare Pagesミドルウェアとして使用できます。

ts
// functions/_middleware.ts
import { handleMiddleware } from 'hono/cloudflare-pages'

export const onRequest = handleMiddleware(async (c, next) => {
  console.log(`You are accessing ${c.req.url}`)
  await next()
})

また、Honoの組み込みおよびサードパーティ製のミドルウェアも使用できます。たとえば、ベーシック認証を追加するには、Honoのベーシック認証ミドルウェアを使用できます。

ts
// functions/_middleware.ts
import { handleMiddleware } from 'hono/cloudflare-pages'
import { basicAuth } from 'hono/basic-auth'

export const onRequest = handleMiddleware(
  basicAuth({
    username: 'hono',
    password: 'acoolproject',
  })
)

複数のミドルウェアを適用する場合は、次のように記述できます。

ts
import { handleMiddleware } from 'hono/cloudflare-pages'

// ...

export const onRequest = [
  handleMiddleware(middleware1),
  handleMiddleware(middleware2),
  handleMiddleware(middleware3),
]

EventContextへのアクセス

EventContextオブジェクトには、handleMiddlewarec.envを介してアクセスできます。

ts
// functions/_middleware.ts
import { handleMiddleware } from 'hono/cloudflare-pages'

export const onRequest = [
  handleMiddleware(async (c, next) => {
    c.env.eventContext.data.user = 'Joe'
    await next()
  }),
]

次に、ハンドラー内のc.env.eventContextを介してデータ値にアクセスできます。

ts
// functions/api/[[route]].ts
import type { EventContext } from 'hono/cloudflare-pages'
import { handle } from 'hono/cloudflare-pages'

// ...

type Env = {
  Bindings: {
    eventContext: EventContext
  }
}

const app = new Hono<Env>()

app.get('/hello', (c) => {
  return c.json({
    message: `Hello, ${c.env.eventContext.data.user}!`, // 'Joe'
  })
})

export const onRequest = handle(app)

MITライセンスに基づいてリリースされています。