Image-Codec-Kontrolle, i18n-Fallback-Routen und ein wichtiger Cloudflare-Fix – mit offenem Starter-Template
SerieCloudflare Platform
Teil 11 von 11
Astro 6.1 erschien am 26. März 2026 – exakt einen Monat nach dem großen 6.0-Release. Es ist kein Architekturwechsel, sondern ein sauber eingegrenztes Minor-Release: drei neue Features, ein relevanter Cloudflare-Fix, keine Breaking Changes.
Wer die fundamentalen Änderungen aus 6.0 noch nicht kennt – Dev-Server auf workerd, Cloudflare-native Integration, Zod 4, Ende von Legacy Collections – findet das im Astro-6-Migrationsleitfaden.
Für alle, die direkt mit 6.1 starten wollen: Das Open-Source-Template astro-v6-template setzt auf dem aktuellen Stand auf – Astro 6.1, Cloudflare-Adapter, Tailwind v4, Svelte 5 Runes, Biome, i18n en/de, CSP und Sessions out of the box.
Sharp: Codec-Parameter direkt konfigurieren
Das nützlichste neue Feature richtet sich an alle, die Bildoptimierung feiner steuern wollen. Bisher war die Ausgabequalität nur über den globalen quality-Parameter einstellbar. Ab 6.1 lassen sich codec-spezifische Optionen direkt in image.service.config setzen:
// astro.config.mjs
export default defineConfig({
image: {
service: {
entrypoint: 'astro/assets/services/sharp',
config: {
jpeg: { mozjpeg: true },
webp: { effort: 6, alphaQuality: 85 },
avif: { chromaSubsampling: '4:2:0' },
png: { compressionLevel: 9 },
}
}
}
});
Unterstützte Codec-Parameter:
| Format | Parameter |
|---|---|
| JPEG | mozjpeg (boolean) |
| WebP | effort, alphaQuality |
| AVIF | chromaSubsampling |
| PNG | compressionLevel |
Per-Image-quality-Overrides (<Image quality={80} />) haben weiterhin Vorrang vor den Defaults. Die Config gilt als projektweiter Baseline.
Wichtiger Cloudflare-Hinweis: Sharp läuft nicht in Cloudflare Workers. Wer auf Workers deployt, setzt den Image-Service auf noop und übernimmt die Bildoptimierung im Build-Schritt:
// astro.config.mjs – Cloudflare-Variante
export default defineConfig({
adapter: cloudflare(),
image: {
service: { entrypoint: 'astro/assets/services/noop' },
},
vite: {
ssr: { external: ['sharp'] },
},
});
So macht es auch das astro-v6-template: Die starter-App nutzt noop für Cloudflare Workers, die blog-App (Cloudflare Pages) kann Sharp im Build einsetzen. Sharp selbst bleibt als Dev-Dependency für lokale Bildverarbeitung installiert.
i18n: Fallback-Routen jetzt für Integrationen sichtbar
Wer i18n.fallbackType: 'rewrite' nutzt, hatte bisher ein stilles Problem mit Sitemaps: Fallback-Routen wurden beim Build generiert, waren aber für Integrationen nicht zugänglich – und fehlten entsprechend in sitemap.xml.
Astro 6.1 behebt das strukturell. Der IntegrationResolvedRoute-Typ bekommt eine neue fallbackRoutes-Property, die über den astro:routes:resolved-Hook zugänglich ist:
// integration.ts
export function myIntegration(): AstroIntegration {
return {
name: 'my-integration',
hooks: {
'astro:routes:resolved': ({ routes }) => {
for (const route of routes) {
// Fallback-Routen sind jetzt sichtbar
console.log(route.fallbackRoutes);
}
},
},
};
}
Das astro-v6-template nutzt eine eigene createSitemapRoute()-Utility statt @astrojs/sitemap – damit lassen sich i18n-Routen und Fallbacks vollständig kontrollieren, ohne auf den offiziellen Adapter angewiesen zu sein. Die i18n-Konfiguration im Template:
// astro.config.mjs
export default defineConfig({
i18n: {
defaultLocale: 'en',
locales: ['en', 'de'],
routing: {
prefixDefaultLocale: false,
},
},
});
Für Projekte ohne i18n-Rewrite-Fallbacks ändert sich nichts. Wer dieses Setup nutzt, bekommt damit endlich korrekte Sitemaps ohne manuelle Workarounds.
Markdown: SmartyPants feingranular konfigurieren
Bisher war markdown.smartypants ein boolean – an oder aus. Ab 6.1 akzeptiert es ein Konfigurationsobjekt:
export default defineConfig({
markdown: {
smartypants: {
dashes: 'oldschool', // -- für En-Dash, --- für Em-Dash
ellipses: true,
backticks: false,
}
}
});
Was die Optionen konkret im Output verändern:
| Option | Eingabe | Ausgabe |
|---|---|---|
ellipses: true | ... | … |
dashes: true | -- | – (En-Dash) |
dashes: 'oldschool' | -- / --- | – / — (En/Em-Dash) |
backticks: true | text” “ | "text" (typografisch) |
openingQuotes / closingQuotes | "text" | „text" (z.B. DE) |
Ein typisches Setup für deutschsprachige Inhalte:
export default defineConfig({
markdown: {
smartypants: {
dashes: 'oldschool',
ellipses: true,
backticks: false,
openingQuotes: { double: '„', single: '‚' },
closingQuotes: { double: '"', single: '\'' },
}
}
});
Relevant für redaktionelle Projekte mit Styleguide-Anforderungen – wer bisher Typografie-Korrekturen manuell im Markdown vorgenommen hat, kann das jetzt zentral konfigurieren.
Cloudflare: Dev-Server-Fix für server:defer
Der einzige Cloudflare-spezifische Change in 6.1 ist ein Bugfix – aber ein relevanter. Bei Projekten, die server:defer (experimentelle deferred Server Rendering) zusammen mit dem Cloudflare-Adapter nutzen, konnte der Dev-Server abstürzen. Das ist jetzt behoben.
server:defer ermöglicht, einzelne Komponenten serverseitig verzögert zu rendern – ähnlich wie React Suspense, aber für Astro-Komponenten:
---
// pages/index.astro
import SlowComponent from '../components/SlowComponent.astro';
---
<SlowComponent server:defer>
<div slot="fallback">Lädt...</div>
</SlowComponent>
Mit dem Fix in 6.1 ist das endlich stabil im Cloudflare-Dev-Setup nutzbar. Die großen Cloudflare-Neuerungen – workerd im Dev-Server, direkter KV/R2-Zugriff ohne Simulation – sind Teil von 6.0 und im Migrationsleitfaden dokumentiert.
Das astro-v6-template als Ausgangspunkt
Statt das alles von Hand zusammenzubauen: Das astro-v6-template ist ein MIT-lizenziertes Monorepo-Starter, der auf Astro 6.1 aufsetzt.
astro-v6-template/
├── apps/
│ ├── starter/ # Landing page + Kontaktformular + i18n
│ └── blog/ # MDX Blog + Content Collections + RSS
├── shared/ # Design Tokens, UI-Komponenten, Utilities
└── e2e/ # Playwright E2E-Tests (28 Tests)
Was aus dem Template direkt nutzbar ist:
| Feature | Details |
|---|---|
| Astro 6.1 | aktueller Stand, wird weitergeführt |
| Cloudflare-Adapter | Sessions via KV, Workers-ready |
| Tailwind v4 | CSS-first Config, OKLCH-Farben, Dark Mode |
| Svelte 5 | Runes API ($state, $derived) |
| i18n | en/de, ohne Prefix auf Default-Locale |
| CSP | SHA-256, Astro-native |
| Biome | Lint + Format, ersetzt ESLint + Prettier |
| Zod v4 | Env, Formulare, API-Validation |
| OG-Images | Satori + resvg, Build-Zeit |
| Post-Build-Audit | SEO, A11y, Links – nach jedem Build |
| Playwright | E2E + axe-core A11y-Scans |
git clone https://github.com/casoon/astro-v6-template
cd astro-v6-template
pnpm install
pnpm dev
Vite 7: Was sich im Unterbau ändert
Astro 6.0 läuft auf Vite 7 – das war kein kleines Unterbau-Update, sondern ein grundlegender Wechsel. Einige Änderungen betreffen direkt, wie Projekte gebaut und betrieben werden. Vite 8 mit Rolldown als Standard-Bundler ist inzwischen erschienen (März 2026); Astro-Support folgt.
Environment API: Das Fundament des neuen Dev-Servers
Der wichtigste Vite-7-Beitrag zur Astro-Architektur ist die Environment API. Sie formalisiert, was Vite bisher implizit hatte – client und ssr als separate Ausführungsumgebungen – und erlaubt Frameworks, beliebig viele Umgebungen zu deklarieren.
Für Cloudflare ist das der entscheidende Baustein: Der Cloudflare Vite Plugin 1.0 nutzt die Environment API, um workerd (die echte Cloudflare-Runtime) direkt in vite dev einzuhängen. Kein Emulations-Layer, kein Node-Polyfill – die Dev-Umgebung ist identisch mit Production. End-User müssen die Environment API nicht selbst konfigurieren. Astro und das Cloudflare-Plugin übernehmen das intern.
Neue Browser-Targets
build.target: 'modules' ist in Vite 7 ungültig. Der neue Default heißt 'baseline-widely-available' und entspricht realen Browser-Versionen: Chrome 107, Edge 107, Firefox 104, Safari 16.0. Das ist ein Sprung gegenüber den alten Defaults (Chrome 87, Safari 14).
Für die meisten Projekte ändert sich im Output nichts Sichtbares – wer aber explizit target: 'modules' in der Vite-Config gesetzt hat, muss es entfernen oder ersetzen:
// vite.config.ts / astro.config.mjs
export default defineConfig({
vite: {
build: {
// 'modules' → entfernen oder:
target: 'baseline-widely-available',
}
}
});
Sass Legacy API entfernt
Wer css.preprocessorOptions.sass.api: 'legacy' oder scss.api: 'legacy' in der Vite-Config hatte, muss das entfernen. Vite 7 unterstützt ausschließlich die moderne Sass-Compiler-API – diese ist seit Vite 5.4 Standard und sollte in den meisten Projekten bereits aktiv sein.
// entfernen:
vite: {
css: {
preprocessorOptions: {
scss: { api: 'legacy' } // ← raus
}
}
}
splitVendorChunkPlugin entfernt
Wer das Plugin genutzt hat, erhält beim Build eine Fehlermeldung. Die Funktionalität lässt sich über build.rollupOptions.output.manualChunks direkt abbilden:
vite: {
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
}
}
}
}
}
Was ich wirklich erwarte: Vite 8
Astro 6.1 läuft auf Vite 7 – und das ist der Stand, der hier beschrieben wird. Vite 8 ist am 12. März 2026 erschienen, aber Astro-Support steht noch aus. Darauf muss ich noch warten.
Was Vite 8 bringt, ist architektonisch der größte Schritt seit Vite 2: Rolldown ersetzt sowohl Rollup als auch esbuild – ein einziger, Rust-basierter Bundler für Dev und Production. Die Zahlen sind bemerkenswert: 10-30x schnellere Production-Builds, 3x schnellerer Dev-Server-Start, 40% schnellere Full Reloads. Ein reales Beispiel: Linear hat seine Build-Zeit von 46 Sekunden auf 6 Sekunden reduziert.
Was das für Astro-Projekte konkret bedeuten wird:
- Unified Bundler: Kein Unterschied mehr zwischen esbuild (Dev) und Rollup (Build) – gleiche Pipeline, konsistentes Verhalten
- Module Federation: Wird möglich, was mit dem alten Dual-Bundler-Setup kaum umsetzbar war
- Persistent Caching: Modul-Level-Caching über Build-Läufe hinweg
- Plugin-Kompatibilität: Rolldown implementiert die Rollup-Plugin-API – bestehende Plugins laufen in den meisten Fällen ohne Änderung
Erste Tests mit Astro und Vite 8 haben funktioniert – aber in Production setze ich es erst ein, wenn der Support offiziell ist.
Was du konkret prüfen musst
Für Astro-6-Projekte reduziert sich der Vite-7-Handlungsbedarf auf wenige Punkte:
api: 'legacy'aus Sass/SCSS-Preprocessor-Config entfernenbuild.target: 'modules'entfernen oder auf'baseline-widely-available'setzensplitVendorChunkPlugin-Import durchmanualChunksersetzen- Node.js mind. 20.19 — Astro 6 verlangt ohnehin 22.12, damit ist das abgedeckt
ESM, Environment API und Cloudflare-Deployment sind transparent oder automatisch durch Astro gehandhabt.
Migration: <ViewTransitions /> → <ClientRouter />
Mit Astro 6 wurde <ViewTransitions /> entfernt. Der Ersatz heißt <ClientRouter /> und kommt aus demselben Paket:
// vorher
import { ViewTransitions } from 'astro:transitions';
<ViewTransitions />
// jetzt
import { ClientRouter } from 'astro:transitions';
<ClientRouter />
Das Verhalten ist identisch – es ist eine Umbenennung, kein Redesign. Ebenfalls deprecated (Entfernung in Astro 7): isTransitionBeforePreparationEvent() und isTransitionBeforeSwapEvent().
JavaScript-Bibliotheken und Seitenwechsel
Das ist der Teil, der in der Praxis am meisten Aufmerksamkeit braucht. Wenn <ClientRouter /> aktiv ist, navigiert Astro client-seitig – der Browser führt kein vollständiges Neuladen durch. Das bedeutet: JavaScript, das beim ersten Seitenaufruf initialisiert wurde, läuft beim nächsten Seitenwechsel nicht automatisch neu.
Für selbst geschriebenes JavaScript gibt es klare Muster. Bei externen Bibliotheken – Slider, Charts, Animationsbibliotheken, Custom Elements – hängt das Verhalten davon ab, wie sie sich initialisieren.
Bundled <script> (Astro-Standard): Läuft nur einmal beim ersten Laden. Bibliotheken, die sich hier selbst initialisieren, sind nach einem Seitenwechsel inaktiv – es sei denn, sie lauschen selbst auf DOM-Änderungen.
<script is:inline data-astro-rerun>: Wird bei jedem Seitenwechsel neu ausgeführt. Geeignet für Initialisierungslogik, die frische DOM-Referenzen braucht. Kein TypeScript, IIFE empfohlen:
<script is:inline data-astro-rerun>
(function () {
const el = document.querySelector('[data-my-component]');
if (!el) return;
// Bibliothek initialisieren
MyLib.init(el);
})();
</script>
astro:page-load Event: Feuert nach jedem Seitenwechsel und beim ersten Laden. Kombinierbar mit normalen <script>-Tags – aber Listener müssen sauber aufgeräumt werden, sonst entstehen doppelte Registrierungen:
document.addEventListener('astro:page-load', () => {
// wird bei jedem Seitenwechsel aufgerufen
MyLib.init();
});
transition:persist: Hält ein Element über Seitenwechsel hinweg im DOM – es wird nicht neu gemountet, der Zustand bleibt erhalten. Sinnvoll für persistente UI-Elemente (Media-Player, globaler Zustand).
Bibliotheken mit eigenem Router-Detection: Manche Libraries (z.B. GSAP ScrollTrigger, Alpine.js) haben eigene Mechanismen zur Re-Initialisierung oder müssen explizit zurückgesetzt werden. Vor dem Einsatz lohnt ein Blick in die Doku des jeweiligen Tools – viele haben inzwischen Astro-spezifische Anleitungen.
Die Faustregel: Je mehr eine Bibliothek beim Initialisieren DOM-Referenzen cacht, desto wahrscheinlicher ist es, dass sie nach einem Seitenwechsel neu initialisiert werden muss.
Praxishinweis: Workers vs. Pages – wrangler 4.77 bricht pages deploy
Wer Astro-Projekte auf Cloudflare deployt, sollte diesen Unterschied kennen – besonders wenn ältere Projekte noch auf Cloudflare Pages laufen.
Der @astrojs/cloudflare-Adapter generiert Worker-Format-Output: dist/server/entry.mjs plus eine wrangler.json mit main, assets-Binding und account_id. Das ist ein normales Workers-Deploy-Format – wrangler deploy funktioniert damit problemlos.
Das Problem: wrangler pages deploy hat in Version 4.77 eine strikte Validierung eingeführt, die genau diese Worker-spezifischen Felder ablehnt. Projekte, die bisher mit wrangler pages deploy deployed wurden und jetzt auf den aktuellen Adapter wechseln, laufen in diesen Fehler:
# Schlägt fehl ab wrangler 4.77
wrangler pages deploy dist --project-name mein-projekt
# Funktioniert
wrangler deploy
Das ist kein Bug im Adapter – es ist die Konsequenz daraus, dass Astro-Output für Workers gedacht ist, nicht für Pages. Wer noch alte Projekte auf Cloudflare Pages betreibt, sollte die Migration auf Workers einplanen. Der Wechsel ist überschaubar:
- In den Cloudflare-Dashboard-Einstellungen das Projekt auf Workers umstellen
wrangler.tomloderwrangler.jsonauf Workers-Format prüfen (sollte der Adapter bereits generieren)- Deployment-Script von
wrangler pages deployaufwrangler deployändern - Custom Domain vom Pages-Projekt auf den Worker übertragen
Pages und Workers sind bei Cloudflare inzwischen zunehmend konvergiert – Workers bieten mehr Kontrolle über Bindings (KV, R2, Durable Objects, Sessions) und sind der empfohlene Weg für Astro-Projekte mit serverseitigem Rendering.
Experimentelles: Was noch in Arbeit ist
Keine neuen experimentellen Flags in 6.1, aber drei laufende Experimente aus 6.0 sind es wert, im Blick zu behalten:
Rust-basierter Compiler: Astro ersetzt schrittweise seinen Go-basierten .astro-Compiler durch eine Rust-Implementierung. Noch experimentell, aber die Richtung ist klar.
Queued Rendering: Neue Rendering-Strategie mit bis zu doppelter Geschwindigkeit in Benchmarks. Kein stabiler Release-Termin bisher.
Route Caching API: Plattform-agnostische Cache-Direktiven für SSR-Routen – besonders interessant für Cloudflare-Projekte, die Caching ohne adapter-spezifischen Code definieren wollen.
Unterm Strich
6.1 macht keine großen Versprechen und hält sie trotzdem. Codec-Kontrolle bei Sharp ist ein lang gewünschtes Feature, der i18n-Sitemap-Fix schließt einen stillen Fehler, und der Cloudflare-Crash-Fix gehört in die Kategorie „hätte nicht passieren sollen, wurde schnell behoben”.
Wer noch auf Astro 5 ist: Der Wechsel lohnt sich wegen 6.0 – 6.1 ist dann ein kostenloser Bonus obendrauf.
npx @astrojs/upgrade