Standardmäßig serverseitig gerendert
Wie PHP läuft Astro-Code auf dem Server. Im Gegensatz zu PHP gibt es standardmäßig statisches HTML ohne JavaScript aus.
Astro ist ein Web-Framework zum Erstellen inhaltsorientierter Websites. Bei der Verwendung von EmDash ersetzt Astro Ihr WordPress-Theme – es übernimmt Templating, Routing und Rendering.
Dieser Leitfaden vermittelt die Grundlagen von Astro, indem er sie auf WordPress-Konzepte abbildet, die Sie bereits verstehen.
Standardmäßig serverseitig gerendert
Wie PHP läuft Astro-Code auf dem Server. Im Gegensatz zu PHP gibt es standardmäßig statisches HTML ohne JavaScript aus.
Kein JS, es sei denn, Sie fügen es hinzu
WordPress lädt jQuery und Theme-Skripte automatisch. Astro sendet nichts an den Browser, es sei denn, Sie fügen es explizit hinzu.
Komponentenbasierte Architektur
Anstelle von verstreuten Template-Tags und Includes wird mit komponierbaren, eigenständigen Komponenten gebaut.
Dateibasiertes Routing
Keine Rewrite-Regeln oder query_vars. Die Dateistruktur in src/pages/ definiert Ihre URLs direkt.
WordPress-Themes haben eine flache Struktur mit magischen Dateinamen. Astro verwendet explizite Verzeichnisse:
| WordPress | Astro | Zweck |
|---|---|---|
index.php, single.php | src/pages/ | Routen (URLs) |
template-parts/ | src/components/ | Wiederverwendbare UI-Teile |
header.php + footer.php | src/layouts/ | Seiten-Wrapper |
style.css | src/styles/ | Globales CSS |
functions.php | astro.config.mjs | Seitenkonfiguration |
Ein typisches Astro-Projekt könnte so aussehen:
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-Dateien sind das Äquivalent zu PHP-Templates in Astro. Jede Datei hat zwei Teile:
----Markierungen) – Serverseitiger Code, ähnlich wie PHP am Anfang eines Templates---// Frontmatter: runs on server, never sent to browserinterface 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>Wichtige Unterschiede zu PHP:
interface Props für Editor-Autovervollständigung und Validierung.Astro-Templates verwenden {curly braces} anstelle von <?php ?>-Tags. Die Syntax ist JSX-ähnlich, gibt aber reines HTML aus.
---import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts");const showTitle = true;---{showTitle && <h1>Neueste Beiträge</h1>}
{posts.length > 0 ? ( <ul> {posts.map(post => ( <li> <a href={`/posts/${post.id}`}>{post.data.title}</a> </li> ))} </ul>) : ( <p>Keine Beiträge gefunden.</p>)}<?php$posts = new WP_Query(['post_type' => 'post']);$show_title = true;?>
<?php if ($show_title): ?> <h1>Neueste Beiträge</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>Keine Beiträge gefunden.</p><?php endif; ?>| Muster | Zweck |
|---|---|
{variable} | Einen Wert ausgeben |
{condition && <Element />} | Bedingtes Rendering |
{condition ? <A /> : <B />} | If/Else |
{items.map(item => <Li>{item}</Li>)} | Schleifen |
Komponenten empfangen Daten über Props (wie Funktionsargumente) und Slots (wie do_action-Einfügepunkte).
---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>Verwendung:
<Card title="Hello" featured> <p>Dieser Inhalt landet im Standard-Slot.</p> <footer slot="footer">Footer-Inhalt</footer></Card><?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 // Kein direktes Äquivalent zu Slots. // WordPress verwendet do_action() für ähnliche Muster: do_action('card_content'); do_action('card_footer'); ?></article>$argsIn WordPress übergibt get_template_part() Daten über das $args-Array. Astro-Props sind typisiert und lassen sich direkt destrukturieren:
---// Type-safe with defaultsinterface Props { title: string; count?: number;}const { title, count = 10 } = Astro.props;---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 umschließen Seiten mit gemeinsamer HTML-Struktur – dem <head>, Header, Footer und allem, was seitenübergreifend geteilt wird. Dies ersetzt header.php + footer.php.
---import "../styles/global.css";
interface Props { title: string; description?: string;}
const { title, description = "Meine EmDash-Website" } = 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>Das Layout in einer Seite verwenden:
---import Base from "../../layouts/Base.astro";---<Base title="Startseite"> <h1>Willkommen</h1> <p>Der Seiteninhalt wird im Slot ausgegeben.</p></Base>Astro bietet mehrere Ansätze für Styling. Der charakteristischste sind scoped Styles.
Styles in einem <style>-Tag werden automatisch auf diese Komponente beschränkt:
<article class="card"> <h2>Titel</h2></article>
<style> /* Betrifft nur .card in DIESER Komponente */ .card { padding: 1rem; border: 1px solid #ddd; }
h2 { color: navy; }</style>Das generierte HTML enthält eindeutige Klassennamen, um das Auslaufen von Styles zu verhindern. Keine Spezifitätskämpfe mehr.
Für globale Styles erstellen Sie eine CSS-Datei und importieren sie in einem Layout:
---import "../styles/global.css";---Die class:list-Direktive ersetzt das manuelle Zusammenbauen von Klassenzeichenketten:
---const { featured, size = "medium" } = Astro.props;---<article class:list={[ "card", size, { featured, "has-border": true }]}>Ausgabe: <article class="card medium featured has-border">
<?php$classes = ['card', $size];if ($featured) $classes[] = 'featured';if (true) $classes[] = 'has-border';?><article class="<?php echo esc_attr(implode(' ', $classes)); ?>">Astro liefert standardmäßig kein JavaScript aus. Dies ist die größte mentale Umstellung von WordPress.
Für einfache Interaktionen füge ein <script>-Tag hinzu:
<button id="menu-toggle">Menü</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 nur einmal.
Für komplexere Interaktivität kann Astro JavaScript-Komponenten (React, Vue, Svelte) bei Bedarf laden. Dies ist optional – die meisten Websites kommen gut mit nur <script>-Tags aus.
---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 Laden der Seite |
client:visible | Wenn Komponente in den Viewport tritt |
client:idle | Wenn der Browser im Leerlauf ist |
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) |
Für CMS-Inhalte verwende die 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 generateexport 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>| WordPress | Astro |
|---|---|
Template-Hierarchie (single-post.php) | Explizite Datei: posts/[slug].astro |
Rewrite-Regeln + query_vars | Dateistruktur |
$wp_query bestimmt Template | URL weist direkt auf Datei hin |
add_rewrite_rule() | Dateien oder Ordner erstellen |
Eine Referenz, um das Astro/EmDash-Äquivalent von WordPress-Funktionen zu finden:
| 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 |
| 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) |
| WordPress | Astro/EmDash |
|---|---|
add_action() | EmDash-Hooks, Astro-Middleware |
add_filter() | EmDash-Hooks |
add_shortcode() | Portable Text benutzerdefinierte Blöcke |
register_block_type() | Portable Text benutzerdefinierte Blöcke |
register_sidebar() | EmDash-Widget-Bereiche |
| Plugins | Astro-Integrationen + EmDash-Plugins |
| WordPress | Astro/EmDash |
|---|---|
register_post_type() | Sammlung in Admin-Oberfläche erstellen |
register_taxonomy() | Taxonomie in Admin-Oberfläche erstellen |
register_meta() | Feld zum Sammlungsschema hinzufügen |
| Beitragsstatus | Eintragsstatus (Entwurf, veröffentlicht, etc.) |
| Beitragsbild | Medien-Referenzfeld |
| Gutenberg-Blöcke | Portable Text-Blöcke |
Der Sprung von WordPress zu Astro ist bedeutend, aber logisch:
Beginnen Sie mit dem Erste-Schritte-Leitfaden, um Ihre erste EmDash-Website zu erstellen, oder erkunden Sie Arbeiten mit Inhalten, um zu lernen, wie Sie CMS-Daten abfragen und darstellen können.