Zum Inhalt springen

Cloudflare Pages ​

Achtung

Für neue Projekte empfiehlt Cloudflare mittlerweile Cloudflare Workers anstelle von Cloudflare Pages. Workers unterstützt statische Assets und bietet einen größeren Funktionsumfang. Wenn du eine neue Fullstack-Anwendung beginnst, siehe Cloudflare Workers + Vite, den Nachfolger dieser Pages-Konfiguration. Der Adapter hono/cloudflare-pages ist veraltet und wird in Hono v5 entfernt.

Cloudflare Pages ist eine Edge-Plattform für Fullstack-Webanwendungen. Sie liefert statische Dateien und dynamische Inhalte aus, die von Cloudflare Workers bereitgestellt werden.

Hono unterstützt Cloudflare Pages vollständig. Die Plattform bietet eine angenehme Entwicklungserfahrung. Der Vite-Entwicklungsserver ist schnell, und die Bereitstellung mit Wrangler geht ebenfalls sehr zügig.

1. Einrichtung ​

Für Cloudflare Pages steht eine Projektvorlage zur Verfügung. Starte dein Projekt mit dem Befehl „create-hono“. Wähle für dieses Beispiel die Vorlage cloudflare-pages aus.

sh
npm create hono@latest my-app
sh
yarn create hono my-app
sh
pnpm create hono my-app
sh
bun create hono@latest my-app
sh
deno init --npm hono my-app

Wechsle nach my-app und installiere die Abhängigkeiten.

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

Unten findest du eine grundlegende Verzeichnisstruktur.

text
./
├── 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 ​

Bearbeite src/index.tsx wie folgt:

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. Ausführen ​

Starte den Entwicklungsserver lokal. Öffne anschließend http://localhost:5173 in deinem Webbrowser.

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

4. Bereitstellung ​

Wenn du ein Cloudflare-Konto hast, kannst du die Anwendung auf Cloudflare bereitstellen. In package.json musst du $npm_execpath auf den Paketmanager deiner Wahl ändern.

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

Über das Cloudflare-Dashboard mit GitHub bereitstellen ​

  1. Melde dich im Cloudflare-Dashboard an und wähle dein Konto aus.
  2. Wähle auf der Konto-Startseite Workers & Pages > Create application > Pages > Connect to Git aus.
  3. Autorisiere dein GitHub-Konto und wähle das Repository aus. Gib unter Set up builds and deployments die folgenden Informationen an:
KonfigurationsoptionWert
Produktionsbranchmain
Build-Befehlnpm run build
Build-Verzeichnisdist

Bindings ​

Du kannst Cloudflare-Bindings wie Variablen, KV, D1 und weitere verwenden. In diesem Abschnitt verwenden wir Variablen und KV.

wrangler.toml erstellen ​

Erstelle zunächst wrangler.toml für lokale Bindings:

sh
touch wrangler.toml

Bearbeite wrangler.toml. Lege eine Variable namens MY_NAME fest.

toml
[vars]
MY_NAME = "Hono"

KV erstellen ​

Erstelle als Nächstes die KV. Führe dazu den folgenden Befehl mit wrangler aus:

sh
wrangler kv namespace create MY_KV --preview

Notiere dir die preview_id aus der folgenden Ausgabe:

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

Gib die preview_id zusammen mit dem Binding-Namen MY_KV an:

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

vite.config.ts bearbeiten ​

Bearbeite 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(),
  ],
})

Bindings in deiner Anwendung verwenden ​

Verwende die Variable und KV in deiner Anwendung. Lege die Typen fest.

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

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

Verwende sie wie folgt:

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>)
})

In der Produktionsumgebung ​

Bei Cloudflare Pages verwendest du wrangler.toml für die lokale Entwicklung. Die Bindings für die Produktionsumgebung richtest du dagegen im Dashboard ein.

Clientseite ​

Mit den Funktionen von Vite kannst du clientseitige Skripte schreiben und in deine Anwendung importieren. Wenn /src/client.ts der Einstiegspunkt des Clients ist, gib ihn einfach im script-Tag an. Außerdem hilft import.meta.env.PROD dabei festzustellen, ob der Code auf einem Entwicklungsserver läuft oder sich in der Build-Phase befindet.

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>
  )
})

Damit das Skript korrekt gebaut wird, kannst du die folgende Beispielkonfiguration für vite.config.ts verwenden.

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',
        }),
      ],
    }
  }
})

Mit dem folgenden Befehl kannst du die Server- und Clientskripte bauen.

sh
vite build --mode client && vite build

Cloudflare-Pages-Middleware ​

Cloudflare Pages verwendet ein eigenes Middleware-System, das sich von der Middleware in Hono unterscheidet. Du kannst es aktivieren, indem du in einer Datei namens _middleware.ts wie folgt onRequest exportierst:

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

Mit handleMiddleware kannst du Hono-Middleware als Cloudflare-Pages-Middleware verwenden.

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()
})

Du kannst auch integrierte und Drittanbieter-Middleware für Hono verwenden. Um beispielsweise Basic-Authentifizierung hinzuzufügen, kannst du Honos Middleware für Basic-Authentifizierung nutzen.

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',
  })
)

Wenn du mehrere Middleware-Funktionen anwenden möchtest, schreibe den Code wie folgt:

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

// ...

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

Auf EventContext zugreifen ​

Du kannst in handleMiddleware über c.env auf das Objekt EventContext zugreifen.

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()
  }),
]

Anschließend kannst du im Handler über c.env.eventContext auf den Datenwert zugreifen:

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>().basePath('/api')

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

export const onRequest = handle(app)

Veröffentlicht unter der MIT-Lizenz.