Astro ist ein Web-Framework zum Erstellen inhaltsorientierter Websites. Bei Verwendung von EmDash ersetzt Astro Ihr WordPress-Theme – es übernimmt Templating, Routing und Rendering.
Dieser Leitfaden vermittelt Astro-Grundlagen, indem er sie auf WordPress-Konzepte abbildet, die Sie bereits verstehen.
Wesentliche Paradigmenwechsel
Standardmäßig serverseitig gerendert
Wie PHP läuft Astro-Code auf dem Server. Anders als PHP gibt es standardmäßig statisches HTML mit null JavaScript aus.
Kein JS, es sei denn Sie fügen es hinzu
WordPress lädt jQuery und Theme-Skripte automatisch. Astro liefert nichts an den Browser, es sei denn, Sie fügen es explizit hinzu.
Komponentenbasierte Architektur
Anstelle verstreuter Template-Tags und Includes bauen Sie mit zusammensetzbaren, eigenständigen Komponenten.
Dateibasiertes Routing
Keine Rewrite-Regeln oder query_vars. Die Dateistruktur in src/pages/ definiert Ihre URLs direkt.
Projektstruktur
WordPress-Themes haben eine flache Struktur mit magischen Dateinamen. Astro verwendet explizite Verzeichnisse:
| WordPress | Astro | Zweck |
|---|---|---|
index.php, single.php | src/pages/ | Routes (URLs) |
template-parts/ | src/components/ | Wiederverwendbare UI |
header.php + footer.php | src/layouts/ | Seiten-Wrapper |
style.css | src/styles/ | Globales CSS |
functions.php | astro.config.mjs | Site-Konfiguration |
Der folgende Baum zeigt ein typisches Astro-Projektlayout:
src/
├── components/ # Reusable UI (Header, PostCard, etc.)
├── layouts/ # Page shells (Base.astro)
├── pages/ # Routes - files become URLs
│ ├── index.astro # → /
│ ├── posts/
│ │ ├── index.astro # → /posts
│ │ └── [slug].astro # → /posts/hello-world
│ └── [slug].astro # → /about, /contact, etc.
└── styles/
└── global.css
Astro-Komponenten
.astro-Dateien sind Astros Äquivalent zu PHP-Templates. Jede Datei hat zwei Teile:
- Frontmatter (zwischen
----Trennzeichen) — Serverseitiger Code, wie PHP am Anfang eines Templates - Template — HTML mit Ausdrücken, wie der Rest eines PHP-Templates
Die folgende Komponente deklariert typisierte Props im Frontmatter und rendert sie im Template:
---
// Frontmatter: runs on server, never sent to browser
interface Props {
title: string;
excerpt: string;
url: string;
}
const { title, excerpt, url } = Astro.props;
---
<!-- Template: outputs HTML -->
<article class="post-card">
<h2><a href={url}>{title}</a></h2>
<p>{excerpt}</p>
</article>
Wesentliche Unterschiede zu PHP:
- Frontmatter ist isoliert. Dort deklarierte Variablen sind im Template verfügbar, aber der Code selbst erreicht niemals den Browser.
- Imports gehören ins Frontmatter. Komponenten, Daten, Utilities – alles wird oben importiert.
- TypeScript funktioniert. Definieren Sie Prop-Typen mit
interface Propsfür Editor-Autovervollständigung und Validierung.
Template-Ausdrücke
Astro-Templates verwenden {geschweifte Klammern} anstelle von <?php ?>-Tags. Die Syntax ist JSX-ähnlich, gibt aber reines HTML aus.
Astro
---
import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts");
const showTitle = true;
---
{showTitle && <h1>Latest Posts</h1>}
{posts.length > 0 ? (
<ul>
{posts.map(post => (
<li>
<a href={`/posts/${post.id}`}>{post.data.title}</a>
</li>
))}
</ul>
) : (
<p>No posts found.</p>
)} PHP
<?php
$posts = new WP_Query(['post_type' => 'post']);
$show_title = true;
?>
<?php if ($show_title): ?>
<h1>Latest Posts</h1>
<?php endif; ?>
<?php if ($posts->have_posts()): ?>
<ul>
<?php while ($posts->have_posts()): $posts->the_post(); ?>
<li>
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</li>
<?php endwhile; wp_reset_postdata(); ?>
</ul>
<?php else: ?>
<p>No posts found.</p>
<?php endif; ?> Ausdrucksmuster
| Muster | Zweck |
|---|---|
{variable} | Wert ausgeben |
{condition && <Element />} | Bedingtes Rendering |
{condition ? <A /> : <B />} | If/else |
{items.map(item => <Li>{item}</Li>)} | Schleifen |
Props und Slots
Komponenten empfangen Daten über Props (wie Funktionsargumente) und Slots (wie do_action-Einfügepunkte).
Astro
---
interface Props {
title: string;
featured?: boolean;
}
const { title, featured = false } = Astro.props;
---
<article class:list={["card", { featured }]}>
<h2>{title}</h2>
<slot />
<slot name="footer" />
</article>Das folgende Markup verwendet diese Komponente und übergibt den Standard-Slot und einen benannten footer-Slot:
<Card title="Hello" featured>
<p>This goes in the default slot.</p>
<footer slot="footer">Footer content</footer>
</Card> PHP
<?php
// Usage: get_template_part('template-parts/card', null, [
// 'title' => 'Hello',
// 'featured' => true
// ]);
$title = $args['title'] ?? '';
$featured = $args['featured'] ?? false;
$class = $featured ? 'card featured' : 'card';
?>
<article class="<?php echo esc_attr($class); ?>">
<h2><?php echo esc_html($title); ?></h2>
<?php
// No direct equivalent to slots.
// WordPress uses do_action() for similar patterns:
do_action('card_content');
do_action('card_footer');
?>
</article> Props vs $args
In WordPress übergibt get_template_part() Daten über das $args-Array. Astro-Props sind typisiert und destrukturiert:
---
// Type-safe with defaults
interface Props {
title: string;
count?: number;
}
const { title, count = 10 } = Astro.props;
---
Slots vs Hooks
WordPress verwendet do_action(), um Einfügepunkte zu erstellen. Astro verwendet Slots:
| WordPress | Astro |
|---|---|
do_action('before_content') | <slot name="before" /> |
| Standard-Inhaltsbereich | <slot /> |
do_action('after_content') | <slot name="after" /> |
Der Unterschied: Slots empfangen Kindelemente an der Aufrufstelle, während WordPress-Hooks separate add_action()-Aufrufe an anderer Stelle erfordern.
Layouts
Layouts umschließen Seiten mit gemeinsamer HTML-Struktur – dem <head>, Header, Footer und allem, was seitenübergreifend geteilt wird. Dies ersetzt header.php + footer.php. Das folgende Layout definiert diese gemeinsame Shell und stellt einen Slot für Seiteninhalte bereit:
---
import "../styles/global.css";
interface Props {
title: string;
description?: string;
}
const { title, description = "My EmDash Site" } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content={description} />
<title>{title}</title>
</head>
<body>
<header>
<nav><!-- Navigation --></nav>
</header>
<main>
<slot />
</main>
<footer>
<p>© {new Date().getFullYear()}</p>
</footer>
</body>
</html>
Verwenden Sie das Layout in einer Seite:
---
import Base from "../layouts/Base.astro";
---
<Base title="Home">
<h1>Welcome</h1>
<p>Page content goes in the slot.</p>
</Base>
Styling
Astro bietet mehrere Styling-Ansätze. Der charakteristischste sind scoped Styles.
Scoped Styles
Styles in einem <style>-Tag werden automatisch auf diese Komponente beschränkt:
<article class="card">
<h2>Title</h2>
</article>
<style>
/* Only affects .card in THIS component */
.card {
padding: 1rem;
border: 1px solid #ddd;
}
h2 {
color: navy;
}
</style>
Das generierte HTML enthält eindeutige Klassennamen, um Style-Leakage zu verhindern, sodass Komponenten-Styles enthalten bleiben, ohne die Selektorspezifität zu eskalieren.
Globale Styles
Für seitenweite Styles erstellen Sie eine CSS-Datei und importieren sie in ein Layout:
---
import "../styles/global.css";
---
Bedingte Klassen
Die class:list-Direktive ersetzt manuelles Klassen-String-Building:
Astro
---
const { featured, size = "medium" } = Astro.props;
---
<article class:list={[
"card",
size,
{ featured, "has-border": true }
]}>Ausgabe: <article class="card medium featured has-border">
PHP
<?php
$classes = ['card', $size];
if ($featured) $classes[] = 'featured';
if (true) $classes[] = 'has-border';
?>
<article class="<?php echo esc_attr(implode(' ', $classes)); ?>"> Clientseitiges JavaScript
Astro liefert standardmäßig null JavaScript. Dies ist die größte mentale Umstellung von WordPress.
Interaktivität hinzufügen
Für einfache Interaktionen fügen Sie ein <script>-Tag hinzu:
<button id="menu-toggle">Menu</button>
<nav id="mobile-menu" hidden>
<slot />
</nav>
<script>
const toggle = document.getElementById("menu-toggle");
const menu = document.getElementById("mobile-menu");
toggle?.addEventListener("click", () => {
menu?.toggleAttribute("hidden");
});
</script>
Skripte werden automatisch gebündelt und dedupliziert. Wenn diese Komponente zweimal auf einer Seite erscheint, läuft das Skript einmal.
Erweiterte interaktive Komponenten
Für komplexere Interaktivität kann Astro JavaScript-Komponenten (React, Vue, Svelte) bei Bedarf laden. Dies ist optional – die meisten Sites funktionieren gut mit nur <script>-Tags. Die folgende Seite lädt eine Komponente nur, wenn sie in den Viewport scrollt:
---
import SearchWidget from "../components/SearchWidget.jsx";
---
<!-- Only load JavaScript when the search box scrolls into view -->
<SearchWidget client:visible />
| Direktive | Wann JavaScript lädt |
|---|---|
client:load | Sofort beim Seitenladen |
client:visible | Wenn Komponente in Viewport eintritt |
client:idle | Wenn Browser idle ist |
Routing
Astro verwendet dateibasiertes Routing. Dateien in src/pages/ werden zu URLs:
| Datei | URL |
|---|---|
src/pages/index.astro | / |
src/pages/about.astro | /about |
src/pages/posts/index.astro | /posts |
src/pages/posts/[slug].astro | /posts/hello-world |
src/pages/[...slug].astro | Beliebiger Pfad (Catch-all) |
Dynamische Routen
Für CMS-Inhalte verwenden Sie Klammer-Syntax für dynamische Segmente:
---
import { getEmDashCollection, getEmDashEntry } from "emdash";
import Base from "../../layouts/Base.astro";
import { PortableText } from "emdash/ui";
// For static builds, define which pages to generate
export async function getStaticPaths() {
const { entries: posts } = await getEmDashCollection("posts");
return posts.map(post => ({
params: { slug: post.id },
props: { post },
}));
}
const { post } = Astro.props;
---
<Base title={post.data.title}>
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article>
</Base>
Im Vergleich zu WordPress
| WordPress | Astro |
|---|---|
Template-Hierarchie (single-post.php) | Explizite Datei: posts/[slug].astro |
Rewrite-Regeln + query_vars | Dateistruktur |
$wp_query bestimmt Template | URL bildet direkt auf Datei ab |
add_rewrite_rule() | Dateien oder Ordner erstellen |
Wo WordPress-Konzepte leben
Eine Referenz zum Finden des Astro/EmDash-Äquivalents von WordPress-Features:
Templating
| WordPress | Astro/EmDash |
|---|---|
| Template-Hierarchie | Dateibasiertes Routing in src/pages/ |
get_template_part() | Komponenten importieren und verwenden |
the_content() | <PortableText value={content} /> |
the_title(), the_*() | Zugriff über post.data.title |
| Template-Tags | Template-Ausdrücke {value} |
body_class() | class:list-Direktive |
Daten und Abfragen
| WordPress | Astro/EmDash |
|---|---|
WP_Query | getEmDashCollection(type, filters) |
get_post() | getEmDashEntry(type, id) |
get_posts() | getEmDashCollection(type) |
get_the_terms() | Zugriff über entry.data.categories |
get_post_meta() | Zugriff über entry.data.fieldName |
get_option() | getSiteSettings() |
wp_nav_menu() | getMenu(location) |
Erweiterbarkeit
| WordPress | Astro/EmDash |
|---|---|
add_action() | EmDash-Hooks, Astro-Middleware |
add_filter() | EmDash-Hooks |
add_shortcode() | Portable Text Custom Blocks |
register_block_type() | Portable Text Custom Blocks |
register_sidebar() | EmDash Widget Areas |
| Plugins | Astro-Integrationen + EmDash-Plugins |
Inhaltstypen
| WordPress | Astro/EmDash |
|---|---|
register_post_type() | Collection in Admin-UI erstellen |
register_taxonomy() | Taxonomie in Admin-UI erstellen |
register_meta() | Feld zu Collection-Schema hinzufügen |
| Post-Status | Entry-Status (draft, published, etc.) |
| Featured Image | Media-Referenzfeld |
| Gutenberg-Blöcke | Portable Text-Blöcke |
Konzept-Mapping
Die wichtigsten WordPress-zu-Astro-Umstellungen, die in diesem Leitfaden behandelt werden:
- PHP-Templates werden zu Astro-Komponenten: Servercode plus HTML, mit expliziter Dateiorganisation.
- Template-Tags werden zu Props und Imports: Daten fließen durch Argumente statt über Globals.
- Theme-Dateien werden zu einem Pages-Verzeichnis: URLs entsprechen der Dateistruktur.
- Hooks werden zu Slots und Middleware: Einfügepunkte werden dort definiert, wo Inhalte übergeben werden.
- jQuery lädt standardmäßig in WordPress; Astro liefert kein JavaScript, bis Sie es hinzufügen.
Beginnen Sie mit dem Getting Started-Leitfaden, um Ihre erste EmDash-Site zu erstellen, oder erkunden Sie Working with Content, um zu lernen, wie man CMS-Daten abfragt und rendert.