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:

  1. Sie generiert den Worker (via Preset “cloudflare_pages”)
  2. Sie generiert die statischen Daten (via Preset “static”)
  3. Sie mischt beides und schiebt ein paar Daten hin und her
  4. 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/websiteCode 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 und CLOUDFLARE_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.

Kategorien:CloudflareVue.JS