Zum Inhalt springen
Frontend

Astro - Moderner Website-Generator mit Islands-Architektur

Veröffentlicht am:
·6 Min. Lesezeit·Autor: MDS Software Solutions Group

Astro Moderner Website-Generator

frontend

Astro - Der moderne Static-Site-Generator

Astro ist ein Web-Framework der naechsten Generation, das den Ansatz zur Erstellung von Websites grundlegend veraendert. Anstatt Kilobytes an JavaScript an den Browser zu senden, generiert Astro sauberes HTML und CSS und fuegt JavaScript nur dort hinzu, wo es wirklich benoetigt wird. Diese "Zero JS by Default"-Philosophie macht Astro-basierte Websites zu den schnellsten Loesungen auf dem Markt.

In diesem Artikel untersuchen wir die Schluesselkonzepte von Astro - von der Islands-Architektur ueber .astro-Komponenten und Content Collections bis hin zum SSR-Modus und Performance-Vergleichen mit Next.js und Gatsby.

Islands-Architektur - Eine Revolution im UI-Aufbau#

Die Islands-Architektur ist Astros wichtigste Innovation. Traditionelle SPA-Frameworks behandeln die gesamte Seite als eine grosse JavaScript-Anwendung - auch wenn der Grossteil des Inhalts statisch ist. Astro kehrt dieses Modell vollstaendig um.

Wie funktionieren Islands?#

In Astro ist jede Seite standardmaessig statisches HTML. Interaktive Elemente - Buttons, Formulare, Karussells - werden als unabhaengige JavaScript-"Inseln" behandelt, die in ein Meer aus statischem HTML eingebettet sind:

---
// src/pages/index.astro
import Header from '../components/Header.astro';
import HeroSection from '../components/HeroSection.astro';
import ProductCarousel from '../components/ProductCarousel.tsx';
import Newsletter from '../components/Newsletter.vue';
import Footer from '../components/Footer.astro';
---

<html lang="de">
  <body>
    <!-- Statisches HTML - kein JavaScript -->
    <Header />
    <HeroSection />

    <!-- Interaktive "Insel" - React, geladen bei Sichtbarkeit -->
    <ProductCarousel client:visible />

    <!-- Interaktive "Insel" - Vue, sofort geladen -->
    <Newsletter client:load />

    <!-- Statisches HTML -->
    <Footer />
  </body>
</html>

Client-Direktiven#

Astro bietet praezise Kontrolle darueber, wann JavaScript geladen wird:

  • client:load - laedt die Komponente sofort beim Seitenaufruf
  • client:idle - laedt, wenn der Browser inaktiv ist (requestIdleCallback)
  • client:visible - laedt, wenn die Komponente im Viewport erscheint (Intersection Observer)
  • client:media - laedt bei Erfuellung einer Media-Query-Bedingung
  • client:only - rendert die Komponente ausschliesslich auf der Client-Seite
---
import HeavyChart from '../components/HeavyChart.tsx';
import MobileMenu from '../components/MobileMenu.svelte';
import ChatWidget from '../components/ChatWidget.tsx';
---

<!-- Diagramm wird erst geladen, wenn der Benutzer dorthin scrollt -->
<HeavyChart client:visible />

<!-- Mobiles Menue wird nur auf kleinen Bildschirmen geladen -->
<MobileMenu client:media="(max-width: 768px)" />

<!-- Chat wird geladen, wenn der Browser inaktiv ist -->
<ChatWidget client:idle />

Diese granulare Kontrolle bedeutet, dass der Benutzer JavaScript nur dann herunterlaed, wenn er es braucht - und nur so viel wie noetig.

Zero JavaScript als Standard#

Im Gegensatz zu Next.js oder Gatsby, wo jede Seite die React-Runtime enthaelt (ca. 40-80 KB gzipped), sendet Astro standardmaessig kein JavaScript. Eine Seite, die ausschliesslich aus .astro-Komponenten besteht, generiert reines HTML und CSS.

---
// src/components/BlogCard.astro
// Diese Komponente rendert zu reinem HTML - kein JS
interface Props {
  title: string;
  excerpt: string;
  date: string;
  slug: string;
}

const { title, excerpt, date, slug } = Astro.props;
const formattedDate = new Date(date).toLocaleDateString('de-DE', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
});
---

<article class="blog-card">
  <time datetime={date}>{formattedDate}</time>
  <h3><a href={`/blog/${slug}`}>{title}</a></h3>
  <p>{excerpt}</p>
</article>

<style>
  .blog-card {
    padding: 1.5rem;
    border-radius: 8px;
    background: var(--surface);
    transition: transform 0.2s ease;
  }
  .blog-card:hover {
    transform: translateY(-2px);
  }
</style>

Die gesamte Komponente oben kompiliert zu statischem HTML und Scoped CSS. Der Browser muss keinerlei JavaScript herunterladen oder parsen.

Framework-agnostisch - React, Vue, Svelte oder alle zusammen#

Eine der einzigartigsten Eigenschaften von Astro ist die Moeglichkeit, Komponenten verschiedener Frameworks in einem einzigen Projekt zu mischen. Sie koennen eine React-Komponente neben einer Vue-Komponente und einer Svelte-Komponente verwenden - Astro kuemmert sich um den Rest.

Einrichtung der Integrationen#

// astro.config.mjs
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import vue from '@astrojs/vue';
import svelte from '@astrojs/svelte';

export default defineConfig({
  integrations: [react(), vue(), svelte()],
});

Praktisches Beispiel#

---
// src/pages/dashboard.astro
// Jede Komponente verwendet ihr eigenes Framework
import ReactDataGrid from '../components/DataGrid.tsx';
import VueFormWizard from '../components/FormWizard.vue';
import SvelteNotifications from '../components/Notifications.svelte';
---

<main>
  <h1>Admin-Dashboard</h1>

  <!-- React - hervorragend fuer komplexe Datentabellen -->
  <ReactDataGrid client:load data={dashboardData} />

  <!-- Vue - ideal fuer mehrstufige Formulare -->
  <VueFormWizard client:visible />

  <!-- Svelte - leichtgewichtig und schnell fuer Benachrichtigungen -->
  <SvelteNotifications client:idle />
</main>

Dieser Ansatz ist besonders wertvoll bei Migrationen - Sie koennen Komponenten schrittweise von einem Framework zu einem anderen verschieben, ohne die gesamte Anwendung auf einmal umschreiben zu muessen.

Astro-Komponenten - Die Kraft der Einfachheit#

.astro-Komponenten sind Astros natives Format, das serverseitige Logik mit einem HTML-Template in einer einzigen Datei kombiniert. Die Syntax aehnelt einer Kombination aus JSX und Frontmatter:

---
// src/components/Navigation.astro
// Der "Fence"-Block --- wird auf dem Server ausgefuehrt
interface Props {
  currentPath: string;
}

const { currentPath } = Astro.props;

const navItems = [
  { href: '/', label: 'Startseite' },
  { href: '/leistungen', label: 'Leistungen' },
  { href: '/portfolio', label: 'Portfolio' },
  { href: '/blog', label: 'Blog' },
  { href: '/kontakt', label: 'Kontakt' },
];

// Top-level await ist moeglich
const response = await fetch('https://api.example.com/announcements');
const announcements = await response.json();
---

<nav class="main-nav">
  <ul>
    {navItems.map((item) => (
      <li>
        <a
          href={item.href}
          class:list={[
            'nav-link',
            { active: currentPath === item.href }
          ]}
        >
          {item.label}
        </a>
      </li>
    ))}
  </ul>

  {announcements.length > 0 && (
    <div class="announcement-bar">
      {announcements[0].message}
    </div>
  )}
</nav>

<style>
  .nav-link {
    text-decoration: none;
    color: var(--text);
    padding: 0.5rem 1rem;
  }
  .nav-link.active {
    color: var(--primary);
    font-weight: 600;
  }
</style>

Wesentliche Merkmale von .astro-Komponenten:

  • Top-level await - Sie koennen Daten direkt in der Komponente abrufen
  • Scoped Styles - Styles sind standardmaessig auf die Komponente beschraenkt
  • Keine Reaktivitaet - sie rendern einmal auf dem Server, was sie extrem schnell macht
  • TypeScript out-of-the-box - volle Unterstuetzung ohne zusaetzliche Konfiguration

Content Collections - Typsichere Inhaltsverwaltung#

Content Collections ist Astros eingebautes Content-Management-System. Es ermoeglicht die Organisation von Blogbeitraegen, Dokumentation oder Produkten mit vollstaendiger Typ-Validierung.

Kollektionen definieren#

// src/content/config.ts
import { defineCollection, z } from 'astro:content';

const blogCollection = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    description: z.string().max(160),
    date: z.coerce.date(),
    updated: z.coerce.date().optional(),
    category: z.enum(['frontend', 'backend', 'devops', 'mobile']),
    tags: z.array(z.string()),
    author: z.string().default('MDS Software Solutions Group'),
    cover: z.string(),
    draft: z.boolean().default(false),
    locale: z.enum(['pl', 'en', 'de']),
  }),
});

const projectsCollection = defineCollection({
  type: 'content',
  schema: z.object({
    name: z.string(),
    client: z.string(),
    technologies: z.array(z.string()),
    year: z.number(),
    featured: z.boolean().default(false),
  }),
});

export const collections = {
  blog: blogCollection,
  projects: projectsCollection,
};

Inhalte abrufen und anzeigen#

---
// src/pages/blog/[...slug].astro
import { getCollection, getEntry } from 'astro:content';
import BlogLayout from '../../layouts/BlogLayout.astro';

export async function getStaticPaths() {
  const posts = await getCollection('blog', ({ data }) => {
    return data.draft !== true && data.locale === 'de';
  });

  return posts.map((post) => ({
    params: { slug: post.slug },
    props: { post },
  }));
}

const { post } = Astro.props;
const { Content, headings } = await post.render();
---

<BlogLayout frontmatter={post.data}>
  <nav class="toc">
    <h2>Inhaltsverzeichnis</h2>
    <ul>
      {headings
        .filter((h) => h.depth <= 3)
        .map((h) => (
          <li style={`margin-left: ${(h.depth - 2) * 1}rem`}>
            <a href={`#${h.slug}`}>{h.text}</a>
          </li>
        ))}
    </ul>
  </nav>
  <Content />
</BlogLayout>

Content Collections validieren automatisch den Frontmatter, generieren TypeScript-Typen und bieten volles IntelliSense in Ihrem Code-Editor.

Dateibasiertes Routing#

Astro verwendet ein dateibasiertes Routing-System innerhalb des Verzeichnisses src/pages/. Es ist intuitiv und erfordert keine Konfiguration:

src/pages/
  index.astro          -> /
  about.astro          -> /about
  blog/
    index.astro        -> /blog
    [slug].astro       -> /blog/:slug (dynamisch)
    [...slug].astro    -> /blog/* (catch-all)
  api/
    search.ts          -> /api/search (API-Endpunkt)

Dynamische Routen mit Parametern#

---
// src/pages/kategorie/[category].astro
import { getCollection } from 'astro:content';

export async function getStaticPaths() {
  const posts = await getCollection('blog');
  const categories = [...new Set(posts.map((p) => p.data.category))];

  return categories.map((category) => ({
    params: { category },
    props: {
      posts: posts.filter((p) => p.data.category === category),
    },
  }));
}

const { category } = Astro.params;
const { posts } = Astro.props;
---

<h1>Kategorie: {category}</h1>
<ul>
  {posts.map((post) => (
    <li>
      <a href={`/blog/${post.slug}`}>{post.data.title}</a>
    </li>
  ))}
</ul>

API-Endpunkte#

// src/pages/api/search.ts
import type { APIRoute } from 'astro';
import { getCollection } from 'astro:content';

export const GET: APIRoute = async ({ url }) => {
  const query = url.searchParams.get('q')?.toLowerCase() || '';
  const posts = await getCollection('blog');

  const results = posts
    .filter((post) =>
      post.data.title.toLowerCase().includes(query) ||
      post.data.description.toLowerCase().includes(query)
    )
    .map((post) => ({
      title: post.data.title,
      slug: post.slug,
      description: post.data.description,
    }));

  return new Response(JSON.stringify(results), {
    headers: { 'Content-Type': 'application/json' },
  });
};

View Transitions API - Fliessende Seitenuebergaenge#

Astro war eines der ersten Frameworks, das die native View Transitions API integriert hat und damit fliessende Uebergangsanimationen zwischen Seiten ermoeglicht - ohne SPA:

---
// src/layouts/BaseLayout.astro
import { ViewTransitions } from 'astro:transitions';
---

<html lang="de">
  <head>
    <ViewTransitions />
  </head>
  <body>
    <slot />
  </body>
</html>

Benutzerdefinierte Animationen#

---
// src/components/BlogCard.astro
import { fade, slide } from 'astro:transitions';
---

<article transition:animate={slide({ duration: '0.3s' })}>
  <img
    src={cover}
    alt={title}
    transition:name={`blog-cover-${slug}`}
  />
  <h3 transition:name={`blog-title-${slug}`}>
    {title}
  </h3>
</article>

Mit transition:name animiert Astro automatisch Elemente mit demselben Bezeichner zwischen Seiten - zum Beispiel geht ein Post-Thumbnail in der Liste fliessend in ein grosses Bild auf der Post-Seite ueber.

SSR-Modus - Serverseitiges Rendering#

Astro unterstuetzt auch dynamisches serverseitiges Rendering (SSR), das den Aufbau vollstaendiger Webanwendungen ermoeglicht:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';

export default defineConfig({
  output: 'server', // oder 'hybrid' fuer einen gemischten Ansatz
  adapter: node({
    mode: 'standalone',
  }),
});

Hybrid-Modus#

Der hybrid-Modus rendert Seiten standardmaessig vor, mit der Moeglichkeit, bestimmte als dynamisch zu kennzeichnen:

---
// src/pages/dashboard.astro
// Diese Seite wird dynamisch gerendert
export const prerender = false;

import { getSession } from '../lib/auth';

const session = await getSession(Astro.request);
if (!session) {
  return Astro.redirect('/login');
}
---

<h1>Willkommen, {session.user.name}!</h1>

Astro bietet Adapter fuer verschiedene Deployment-Plattformen: Node.js, Vercel, Netlify, Cloudflare Workers, Deno und weitere.

Integrationen - Tailwind, MDX und mehr#

Das Astro-Oekosystem bietet eine umfangreiche Sammlung offizieller und Community-Integrationen:

# Integrationen mit einem einzigen Befehl installieren
npx astro add tailwind
npx astro add mdx
npx astro add sitemap
npx astro add image

Konfiguration mit Tailwind CSS#

// astro.config.mjs
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
import mdx from '@astrojs/mdx';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  site: 'https://example.com',
  integrations: [
    tailwind({
      applyBaseStyles: false,
    }),
    mdx(),
    sitemap({
      filter: (page) => !page.includes('/admin/'),
    }),
  ],
});

MDX mit benutzerdefinierten Komponenten#

---
title: Wie man die Website-Performance optimiert
---

import Callout from '../../components/Callout.astro';
import CodePlayground from '../../components/CodePlayground.tsx';

# Wie man die Website-Performance optimiert

<Callout type="tip">
  Astro optimiert Bilder automatisch - keine zusaetzlichen Tools erforderlich.
</Callout>

## Live-Beispiel

<CodePlayground client:visible code={`console.log('Hello Astro!')`} />

Bildoptimierung#

Astro bietet eingebaute Bildoptimierung ueber die <Image />-Komponente:

---
import { Image } from 'astro:assets';
import heroImage from '../assets/hero.jpg';
---

<!-- Automatische Optimierung: WebP/AVIF-Konvertierung, responsive Groessen -->
<Image
  src={heroImage}
  alt="Bildbeschreibung"
  widths={[400, 800, 1200]}
  sizes="(max-width: 800px) 100vw, 800px"
  format="webp"
  quality={80}
/>

<!-- Remote-Bilder mit angegebenen Abmessungen -->
<Image
  src="https://example.com/photo.jpg"
  alt="Entferntes Foto"
  width={800}
  height={600}
  format="avif"
/>

Astro generiert automatisch passende Groessen, konvertiert in moderne Formate und fuegt width/height-Attribute hinzu, um Layout-Verschiebungen (CLS) zu vermeiden.

Astro DB - Eingebaute Datenbank#

Astro DB ist eine Datenbanklosung basierend auf libSQL (einem SQLite-Fork), die speziell fuer die Zusammenarbeit mit Astro entwickelt wurde:

// db/config.ts
import { defineDb, defineTable, column } from 'astro:db';

const Comment = defineTable({
  columns: {
    id: column.number({ primaryKey: true }),
    postSlug: column.text(),
    author: column.text(),
    content: column.text(),
    createdAt: column.date({ default: new Date() }),
    approved: column.boolean({ default: false }),
  },
});

export default defineDb({
  tables: { Comment },
});
---
// src/pages/blog/[slug].astro
import { db, Comment, eq } from 'astro:db';

const comments = await db
  .select()
  .from(Comment)
  .where(eq(Comment.postSlug, slug))
  .where(eq(Comment.approved, true))
  .orderBy(Comment.createdAt);
---

<section class="comments">
  {comments.map((comment) => (
    <div class="comment">
      <strong>{comment.author}</strong>
      <p>{comment.content}</p>
      <time>{comment.createdAt.toLocaleDateString('de-DE')}</time>
    </div>
  ))}
</section>

Performance-Vergleich mit Next.js und Gatsby#

Astro gewinnt konsequent in Performance-Benchmarks fuer inhaltsgetriebene Websites:

An den Client gesendetes JavaScript#

| Framework | Startseite (typisch) | Blogbeitrag | |-----------|---------------------|-------------| | Astro | 0 KB | 0 KB | | Next.js | ~85 KB | ~85 KB | | Gatsby | ~70 KB | ~70 KB |

Core Web Vitals Metriken (typische Blog-Seite)#

| Metrik | Astro | Next.js | Gatsby | |--------|-------|---------|--------| | LCP | ~0,8s | ~1,5s | ~1,8s | | FID | ~5ms | ~30ms | ~25ms | | CLS | 0 | ~0,05 | ~0,08 | | TTFB | ~50ms | ~80ms | ~60ms |

Der Unterschied ist besonders auf mobilen Geraeten mit langsamer Verbindung spuerbar - kein JavaScript zum Herunterladen und Parsen bedeutet sofortiges Laden der Seite.

Build-Zeit (1.000 Markdown-Seiten)#

| Framework | Build-Zeit | |-----------|-----------| | Astro | ~15s | | Next.js | ~45s | | Gatsby | ~90s |

Wann sollte man Astro waehlen?#

Astro ist ideal fuer:#

  • Blogs und inhaltsgetriebene Websites - maximale Performance fuer statische Inhalte
  • Unternehmenswebsites und Portfolios - schnelles Laden, hervorragendes SEO
  • Technische Dokumentation - Content Collections und MDX
  • Landing Pages - minimales JS, sofortiges Laden
  • E-Commerce-Storefronts - Seitengeschwindigkeit beeinflusst Konversionen direkt
  • Mehrsprachige Websites - eingebaute i18n-Unterstuetzung

Wann Alternativen in Betracht ziehen:#

  • Komplexe SPA-Anwendungen (z.B. Echtzeit-Dashboards) - Next.js oder SvelteKit
  • Anwendungen mit staendiger Interaktivitaet - React/Vue SPA
  • Full-Stack mit schwerem Backend - Next.js, Remix oder NestJS

Schnellstart mit Astro#

# Neues Projekt erstellen
npm create astro@latest my-astro-site

# Zum Projektverzeichnis navigieren
cd my-astro-site

# Integrationen hinzufuegen
npx astro add tailwind
npx astro add mdx

# Entwicklungsserver starten
npm run dev

Fazit#

Astro ist ein Framework, das die Regeln der Website-Entwicklung veraendert. Mit seiner Islands-Architektur, dem "Zero JavaScript by Default"-Ansatz und der Multi-Framework-Unterstuetzung bietet es eine einzigartige Kombination aus Performance und Flexibilitaet.

Wenn Sie eine Website aufbauen, bei der der Inhalt im Vordergrund steht - einen Blog, eine Unternehmenswebsite, Dokumentation oder eine Landing Page - sollte Astro Ihre erste Wahl sein. Die Core Web Vitals Ergebnisse sprechen fuer sich.


Planen Sie den Aufbau einer modernen Website mit Fokus auf Performance und SEO? Das Team von MDS Software Solutions Group ist spezialisiert auf die Entwicklung leistungsstarker Webanwendungen mit Astro, Next.js und anderen modernen Technologien. Kontaktieren Sie uns - wir helfen Ihnen, die beste Loesung zu waehlen und eine Website zu erstellen, die durch Geschwindigkeit beeindruckt.

Autor
MDS Software Solutions Group

Team von Programmierexperten, die sich auf moderne Webtechnologien spezialisiert haben.

Astro - Moderner Website-Generator mit Islands-Architektur | MDS Software Solutions Group | MDS Software Solutions Group