PDFs in Astro mit Cloudflare Browser… | LaunchFast
LaunchFast Logo LaunchFast
Blog
1.592 Wörter 8 Min. Lesezeit

PDFs in Astro mit Cloudflare Browser Rendering am Edge generieren

Erfahren Sie, wie Sie Rechnungen, Berichte und OG-Bilder als PDFs direkt aus Ihren Astro-Seiten mit Cloudflare Browser Rendering erzeugen. Headless Chromium am Edge ausführen, Print-CSS anwenden und PDFs mit minimaler Latenz streamen.

Rishi Raj Jain
Rishi Raj Jain Autor
Generating PDFs in Astro with Cloudflare Browser Rendering at the Edge

Die serverseitige PDF-Erzeugung bedeutet oft Lambda-Cold-Starts, Chromium-Binaries oder Drittanbieter-APIs mit extra Latenz und Kosten. Wer schon einmal einen Docker-Container mit über 1 GB nur für HTML-zu-PDF gestartet hat, kennt das Problem.

Sponsored

Hochwertige Starter-Kits mit integriertem Authentifizierungsfluss (Auth.js), Objekt-Uploads (AWS, Clouflare R2, Firebase Storage, Supabase Storage), integrierten Zahlungen (Stripe, LemonSqueezy), E-Mail-Verifizierungsablauf (Resend, Postmark, Sendgrid) und viel mehr . Kompatibel mit jeder Datenbank (Redis, Postgres, MongoDB, SQLite, Firestore).

Get all 3 kits Bundle ↗

One-time license · Lifetime updates

Cloudflare Browser Rendering dreht dieses Modell um: ein verwalteter Headless-Chromium-Dienst auf Cloudflares Edge-Netzwerk — keine Binaries, keine Cold-Starts, keine Docker-Layer. Sie erhalten Puppeteer-kompatible APIs mit Startzeiten unter 100 ms, global verteilt.

In dieser Anleitung bauen Sie ein produktionsreifes PDF-System mit Astro, Cloudflare KV und Cloudflare Workers. Sie erstellen druckbare Belegseiten mit eigenem CSS, verdrahten einen API-Endpunkt, der Headless Chrome am Edge startet, und cachen die Ergebnisse in Cloudflare KV, um doppeltes Rendering zu vermeiden.

Voraussetzungen

Sie benötigen:

Warum Cloudflare Browser Rendering für PDFs?

  • Kein Chromium-Pflegeaufwand: Cloudflare betreibt und patcht Headless Chromium für Sie.
  • Edge-Nähe: PDFs nahe am Anfragenden rendern — ideal für Dashboards, Rechnungen und OG-Bilder.
  • Streaming: PDFs direkt aus dem Worker senden, ohne temporäre Dateien.
  • Kostenbewusst: Nutzungsbasierte Abrechnung ohne eigene Renderer-Flotte.

Architekturüberblick

1. Astro-Seite (src/pages/receipt/[id].astro)
→ SSR-Route mit Beleg-/Rechnungs-HTML + Print-CSS
2. PDF-API (src/pages/api/pdf/[id].ts)
→ Browser-Rendering-Session starten
→ Astro-Route-URL laden
→ page.pdf() aufrufen und Binary streamen
3. Cloudflare-Adapter + Browser-Binding
→ Astro auf Workers/Pages deployen
→ BROWSER-Binding für den Worker bereitstellen

Neue Astro-Anwendung erstellen

Starten Sie mit einem neuen Astro-Projekt. Führen Sie aus:

Terminal window
npm create astro@latest my-astro-kv-pdf-app
cd my-astro-kv-pdf-app
npm install wrangler @cloudflare/puppeteer

Wählen Sie bei den Prompts:

  • Use minimal (empty) template, wenn gefragt wird, wie das Projekt starten soll.
  • Yes, wenn Abhängigkeiten installiert werden sollen.
  • Yes, wenn ein Git-Repository initialisiert werden soll.

Danach ins Projektverzeichnis wechseln und die App starten:

Terminal window
npm run dev

Die App läuft unter localhost:4321.

Cloudflare-Adapter in Ihr Astro-Projekt integrieren

Für Cloudflare Workers und Cloudflare KV installieren Sie den Cloudflare-Adapter:

Terminal window
npx astro add cloudflare --yes

Setzen Sie in astro.config.mjs output auf server:

astro.config.mjs
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare()
});

Browser Rendering in wrangler.jsonc konfigurieren

Fügen Sie ein BROWSER-Binding hinzu, damit der Worker Headless Chromium starten kann:

wrangler.jsonc
{
"main": "dist/_worker.js/index.js",
"name": "my-astro-kv-pdf-app",
"compatibility_date": "2025-12-06",
"compatibility_flags": [
"nodejs_compat",
"global_fetch_strictly_public"
],
"assets": {
"binding": "ASSETS",
"directory": "./dist"
},
"observability": {
"enabled": true
},
"browser": {
"binding": "BROWSER"
}
}

Der Block browser stellt Cloudflares Browser-Rendering-Dienst bereit und macht ihn als env.BROWSER im Worker verfügbar.

KV für Caching hinzufügen

Erstellen Sie einen KV-Namespace für generierte PDFs:

Terminal window
npx wrangler kv namespace create PDF_CACHE

Die Ausgabe enthält eine id für wrangler.jsonc. Ergänzen Sie das KV-Binding:

wrangler.jsonc
{
"main": "dist/_worker.js/index.js",
"name": "my-astro-kv-pdf-app",
"compatibility_date": "2025-12-06",
"compatibility_flags": [
"nodejs_compat",
"global_fetch_strictly_public"
],
"assets": {
"binding": "ASSETS",
"directory": "./dist"
},
"observability": {
"enabled": true
},
"browser": {
"binding": "BROWSER"
},
"kv_namespaces": [
{
"binding": "PDF_CACHE",
"id": "generated-id",
"remote": true
}
]
}

TypeScript-Typen hinzufügen

Erstellen Sie src/env.d.ts für die Cloudflare-Bindings:

src/env.d.ts
/// <reference types="astro/client" />
type KVNamespace = import('@cloudflare/workers-types').KVNamespace
type ENV = {
PDF_CACHE: KVNamespace
BROWSER: Fetcher
}
type Runtime = import('@astrojs/cloudflare').Runtime<ENV>
declare namespace App {
interface Locals extends Runtime {}
}

Damit sind locals.runtime.env.PDF_CACHE und locals.runtime.env.BROWSER in Ihren Routen typisiert.

Druckbare Astro-Seite erstellen

Belegseite mit druckfreundlichen Styles:

---
const { id } = Astro.params;
const order = {
id,
customer: 'Ada Lovelace',
total: '$128.00',
items: [
{ name: 'Edge Functions', price: '$50.00' },
{ name: 'PDF Rendering', price: '$78.00' }
]
};
---
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Receipt #{order.id}</title>
<style>
:root { font-family: 'Inter', system-ui, -apple-system, sans-serif; }
body { margin: 0; padding: 32px; color: #0f172a; }
header { display: flex; align-items: center; justify-content: space-between; }
table { width: 100%; border-collapse: collapse; margin-top: 24px; }
th, td { padding: 12px 8px; text-align: left; border-bottom: 1px solid #e2e8f0; }
.total { text-align: right; font-size: 1.125rem; font-weight: 700; }
@page { margin: 24mm; }
@media print {
body { background: white; }
a[href]::after { content: ''; }
}
</style>
</head>
<body>
<header>
<div>
<h1>Receipt #{order.id}</h1>
<p>Issued to {order.customer}</p>
</div>
<strong>launchfa.st</strong>
</header>
<table>
<thead>
<tr><th>Item</th><th>Price</th></tr>
</thead>
<tbody>
{order.items.map(item => (
<tr>
<td>{item.name}</td>
<td>{item.price}</td>
</tr>
))}
</tbody>
</table>
<p class="total">Total: {order.total}</p>
</body>
</html>

Speichern als src/pages/receipt/[id].astro. Das Print-CSS (@page) setzt Ränder; @media print entfernt störende Link-Dekorationen.

PDF-API-Route erstellen

Worker-API-Route mit Cloudflare Browser Rendering: PDF aus der Astro-HTML-Belegseite erzeugen und cachen.

Unter src/pages/api/pdf/[id].ts:

  • prüfen, ob ein PDF in Cloudflare KV liegt, und es sofort zurückgeben
  • bei Cache-Miss Headless-Browser über Browser Rendering starten
  • zur druckbaren Seite navigieren und PDF erzeugen
  • PDF sieben Tage in KV speichern
src/pages/api/pdf/[id].ts
import type { APIRoute } from "astro";
import puppeteer from "@cloudflare/puppeteer";
// Helper to create a proper PDF HTTP response
const pdfResponse = (pdf: Buffer<ArrayBuffer>, id: string) => {
return new Response(pdf, {
headers: {
'Content-Type': 'application/pdf',
'CDN-Cache-Control': 'max-age=604800',
'Content-Disposition': `inline; filename="receipt-${id}.pdf"`
}
});
}
export const GET: APIRoute = async ({ locals, params, request }) => {
const id = params.id as string;
const origin = new URL(request.url).origin;
const targetUrl = `${origin}/receipt/${id}`;
const cache = locals.runtime.env.PDF_CACHE;
// Try KV cache first to avoid unnecessary browser work
const cachedPdf = await cache.get(targetUrl, "arrayBuffer");
if (cachedPdf)
return pdfResponse(Buffer.from(cachedPdf), id);
// Only run browser in Cloudflare's env
if (!locals.runtime.env.BROWSER)
return new Response('Browser binding not available locally', { status: 501 });
// Launch browser and render HTML to PDF
const session = await puppeteer.launch(locals.runtime.env.BROWSER);
const page = await session.newPage();
await page.goto(targetUrl, { waitUntil: 'networkidle0' });
const pdf = await page.pdf({
format: 'A4',
printBackground: true,
margin: { top: '24mm', right: '18mm', bottom: '24mm', left: '18mm' }
});
await session.close();
const result = Buffer.from(pdf);
// Cache for a week (604800 seconds)
await cache.put(targetUrl, result, { expirationTtl: 60 * 60 * 24 * 7 });
return pdfResponse(result, id);
};

Unter /api/pdf/123 erhalten Sie ein live aus /receipt/123 erzeugtes PDF. Folgeanfragen liefern das gecachte PDF bis zum Ablauf.

PDFs schützen und cachen

  • Auth: Vor dem Rendern Session-Token oder signierte Query-Strings verlangen. Unauthentifizierte Anfragen früh ablehnen.
  • Caching: Statische Rechnungen kurz cachen (Cache-Control: public, max-age=300). Dynamische Inhalte privat halten.
  • Rate Limits: Bei hohem Traffic einen Rate Limiter (KV) ergänzen.

Auf Cloudflare Workers deployen

Terminal window
# Build the project
npm run build
# Deploy to Cloudflare Workers
npx wrangler deploy

Nach dem Deploy ist die API unter https://your-worker.workers.dev/api/pdf/[id] erreichbar.

Fazit

Cloudflare Browser Rendering macht PDF-Erzeugung zu einer leichten Edge-Funktion. Astro SSR plus Headless Chromium am Edge liefert Rechnungen, Belege und Reports on-demand — ohne Infrastruktur und ohne Cold-Starts.

Für fortgeschrittene Fälle: Mehrseitige Dokumente, eigene Kopf-/Fußzeilen oder Screenshots für Open-Graph-Bilder. Die Browser-Rendering-API bietet volle Puppeteer-Kontrolle am Cloudflare-Edge.

Fragen oder Anmerkungen? Schreiben Sie mir auf Twitter.

Weiterlesen