Astro für WordPress-Entwickler

Auf dieser Seite

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:

WordPressAstroZweck
index.php, single.phpsrc/pages/Routes (URLs)
template-parts/src/components/Wiederverwendbare UI
header.php + footer.phpsrc/layouts/Seiten-Wrapper
style.csssrc/styles/Globales CSS
functions.phpastro.config.mjsSite-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:

  1. Frontmatter (zwischen ----Trennzeichen) — Serverseitiger Code, wie PHP am Anfang eines Templates
  2. 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 Props fü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

MusterZweck
{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:

WordPressAstro
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>&copy; {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 />
DirektiveWann JavaScript lädt
client:loadSofort beim Seitenladen
client:visibleWenn Komponente in Viewport eintritt
client:idleWenn Browser idle ist

Routing

Astro verwendet dateibasiertes Routing. Dateien in src/pages/ werden zu URLs:

DateiURL
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].astroBeliebiger 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

WordPressAstro
Template-Hierarchie (single-post.php)Explizite Datei: posts/[slug].astro
Rewrite-Regeln + query_varsDateistruktur
$wp_query bestimmt TemplateURL 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

WordPressAstro/EmDash
Template-HierarchieDateibasiertes 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-TagsTemplate-Ausdrücke {value}
body_class()class:list-Direktive

Daten und Abfragen

WordPressAstro/EmDash
WP_QuerygetEmDashCollection(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

WordPressAstro/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
PluginsAstro-Integrationen + EmDash-Plugins

Inhaltstypen

WordPressAstro/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-StatusEntry-Status (draft, published, etc.)
Featured ImageMedia-Referenzfeld
Gutenberg-BlöckePortable 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.