CF Pages, nuxt, teilweise statisch, teilweise dynamisch
Ich möchte eine Webseite auf Cloudflare Pages publishen. Diese Seite soll:
- primär nur aus statischen HTML-Dateien bestehen
- allerdings auch die API-Routes als Worker zur Verfügung stellen
Ziel ist quasi “vorgerendert, allerdings den Worker auch mitnehmen” – eine Kombination aus dem Preset cloudflare_pages
und static
.
Als Framework benutze ich Nuxt 3. Als Pipeline, wie immer, Drone CI.
Die _routes.json
Über die _routes.json
geben wir Cloudflare die Info, welche Routen er an unseren Worker senden soll. Das sind nur die, die mit /api/ anfangen. Im Projektstammverzeichnis erstellen wir also die Datei mit dem folgenden Inhalt:
{
"version": 1,
"include": [
"/api/*"
],
"exclude": [ ]
}
Code language: JSON / JSON with Comments (json)
Wenn wir nun einige Endpunkte ausnehmen wollen würden, könnten wir die in den exlude packen; der exclude hat immer Vorrang vor dem include.
Die Pipeline
Unsere pipeline macht nun folgendes:
- Sie generiert den Worker (via Preset “cloudflare_pages”)
- Sie generiert die statischen Daten (via Preset “static”)
- Sie mischt beides und schiebt ein paar Daten hin und her
- Und haut das via Wrangler in the cloud
Inhalt unserer .drone.yml
:
kind: pipeline
name: default
steps:
- name: render-worker
image: node:22
volumes:
- name: cache
path: /drone/src/node_modules
environment:
NITRO_PRESET: "cloudflare_pages"
commands:
- npm install
- npm run build
- name: render-static
image: node:22
volumes:
- name: cache
path: /drone/src/node_modules
environment:
NITRO_PRESET: "static"
commands:
# - npm install
- npm run generate
- name: build-project
image: node:22
commands:
- cp -r dist/_worker.js .output/public/
- rm -r dist
- mv .output/public dist
- cp _routes.json dist
- name: deploy-to-cloudflare
image: node:22
environment:
CLOUDFLARE_ACCOUNT_ID:
from_secret: CLOUDFLARE_ACCOUNT_ID
CLOUDFLARE_API_TOKEN:
from_secret: CLOUDFLARE_API_TOKEN
volumes:
- name: cache
path: /drone/src/node_modules
commands:
- npx wrangler pages deploy ./dist --project-name=XXXXXXX
trigger:
event:
- tag
- custom
volumes:
- name: cache
host:
path: /tmp/drone/website
Code language: YAML (yaml)
Hier ein paar Anmerkungen:
- in dieser Pipeline wird ein Volume gemountet, in dem wir die node_modules cachen. Dies erfordert, dass das Repo trusted ist. Alternative kann auch jeder Teil mit “volumes” rausgelöscht werden, dann dauern builds nur immer etwas länger.
- wir brauchen die Secrets
CLOUDFLARE_ACCOUNT_ID
undCLOUDFLARE_API_TOKEN
- in dem letzten Schritt muss unser Projektname noch einmal angepasst werden, damit er mit dem von Cloudflare übereinstimmt
Dieser Weg ist übrigens kein offizieller Weg. Ich bin mir nicht sicher, ob das von nuxt gewollt ist, dass sich verschiedene Builds so mergen lassen; er funktioniert allerdings in der Praxis aktuell stabil.