EmDash stellt Abfragefunktionen bereit, um Inhalte in Ihren Astro-Seiten und -Komponenten zu laden. Sie folgen dem Muster der Live Content Collections von Astro und liefern strukturierte Ergebnisse mit Fehlerbehandlung.
Abfragefunktionen
EmDash exportiert zwei zentrale Abfragefunktionen:
| Funktion | Zweck | Rückgabe |
|---|---|---|
getEmDashCollection | Alle Einträge eines Inhaltstyps | { entries, error } |
getEmDashEntry | Einzelnen Eintrag per ID oder Slug | { entry, error, isPreview } |
Import aus emdash:
import { getEmDashCollection, getEmDashEntry } from "emdash";
Alle Einträge abrufen
Mit getEmDashCollection laden Sie alle Einträge eines Inhaltstyps:
---
import { getEmDashCollection } from "emdash";
const { entries: posts, error } = await getEmDashCollection("posts");
if (error) {
console.error("Failed to load posts:", error);
}
---
<ul>
{posts.map((post) => (
<li>{post.data.title}</li>
))}
</ul>
Nach Locale filtern
Wenn i18n aktiviert ist, filtern Sie nach Locale, um Inhalte in einer bestimmten Sprache zu laden:
// Französische Beiträge
const { entries: frenchPosts } = await getEmDashCollection("posts", {
locale: "fr",
status: "published",
});
// Aktuelle Request-Locale
const { entries: localizedPosts } = await getEmDashCollection("posts", {
locale: Astro.currentLocale,
status: "published",
});
Für einzelne Einträge übergeben Sie locale als drittes Argument:
const { entry: post } = await getEmDashEntry("posts", "my-post", {
locale: Astro.currentLocale,
});
Ohne locale gilt die aktuelle Request-Locale. Fehlt eine Übersetzung, wird die Fallback-Kette genutzt.
Nach Status filtern
Nur veröffentlichte oder nur Entwürfe:
// Nur veröffentlichte Beiträge
const { entries: published } = await getEmDashCollection("posts", {
status: "published",
});
// Nur Entwürfe
const { entries: drafts } = await getEmDashCollection("posts", {
status: "draft",
});
Ergebnisse begrenzen
Anzahl der zurückgegebenen Einträge begrenzen:
// Die 5 neuesten Beiträge
const { entries: recentPosts } = await getEmDashCollection("posts", {
status: "published",
limit: 5,
});
Nach Taxonomie filtern
Einträge nach Kategorie, Tag oder benutzerdefinierten Begriffen:
// Beiträge in der Kategorie "news"
const { entries: newsPosts } = await getEmDashCollection("posts", {
status: "published",
where: { category: "news" },
});
// Beiträge mit dem Tag "javascript"
const { entries: jsPosts } = await getEmDashCollection("posts", {
status: "published",
where: { tag: "javascript" },
});
// Mehrere Begriffe (ODER)
const { entries: featuredNews } = await getEmDashCollection("posts", {
status: "published",
where: { category: ["news", "featured"] },
});
Der where-Filter nutzt ODER-Logik, wenn mehrere Werte für eine Taxonomie angegeben sind.
Fehlerbehandlung
Bei Zuverlässigkeitsanforderungen immer auf Fehler prüfen:
const { entries: posts, error } = await getEmDashCollection("posts");
if (error) {
console.error("Failed to load posts:", error);
return new Response("Server error", { status: 500 });
}
Einzelnen Eintrag abrufen
getEmDashEntry lädt einen Eintrag per ID oder Slug:
---
import { getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";
const { slug } = Astro.params;
const { entry: post, error } = await getEmDashEntry("posts", slug);
if (error) {
return new Response("Server error", { status: 500 });
}
if (!post) {
return Astro.redirect("/404");
}
---
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article>
Rückgabetyp
getEmDashEntry liefert ein Ergebnisobjekt:
interface EntryResult<T> {
entry: ContentEntry<T> | null; // null wenn nicht gefunden
error?: Error; // Nur bei echten Fehlern (nicht „nicht gefunden“)
isPreview: boolean; // true bei Vorschau/Entwurf
}
interface ContentEntry<T> {
id: string;
data: T;
edit: EditProxy; // Annotationen für visuelles Bearbeiten
}
Das data-Objekt enthält alle Felder des Inhaltstyps. Der edit-Proxy liefert Annotationen für visuelles Bearbeiten (siehe unten).
Vorschaumodus
EmDash behandelt die Vorschau über die Middleware. Enthält die URL einen gültigen _preview-Token, wird der Kontext gesetzt; die Abfragefunktionen liefern Entwurfsinhalte ohne spezielle Parameter:
---
import { getEmDashEntry } from "emdash";
const { slug } = Astro.params;
// Keine spezielle Vorschau-Logik — Middleware übernimmt das
const { entry, isPreview, error } = await getEmDashEntry("posts", slug);
if (error) {
return new Response("Server error", { status: 500 });
}
if (!entry) {
return Astro.redirect("/404");
}
---
{isPreview && (
<div class="preview-banner">
Vorschau. Dieser Inhalt ist nicht veröffentlicht.
</div>
)}
<article>
<h1>{entry.data.title}</h1>
<PortableText value={entry.data.content} />
</article>
Visuelles Bearbeiten
Jeder Eintrag enthält einen edit-Proxy zum Annotieren der Templates. Auf Elemente spreaden für Inline-Bearbeitung:
<article {...entry.edit}>
<h1 {...entry.edit.title}>{entry.data.title}</h1>
<div {...entry.edit.content}>
<PortableText value={entry.data.content} />
</div>
</article>
Im Bearbeitungsmodus erzeugt {...entry.edit.title} ein data-emdash-ref-Attribut für die Toolbar. In der Produktion keine Ausgabe — kein Laufzeit-Overhead.
Sortierung
getEmDashCollection garantiert keine Reihenfolge. Sortieren Sie im Template:
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
// Nach Veröffentlichungsdatum, neueste zuerst
const sorted = posts.sort(
(a, b) => (b.data.publishedAt?.getTime() ?? 0) - (a.data.publishedAt?.getTime() ?? 0),
);
Häufige Sortiermuster
// Alphabetisch nach Titel
posts.sort((a, b) => a.data.title.localeCompare(b.data.title));
// Nach benutzerdefiniertem order-Feld
posts.sort((a, b) => (a.data.order ?? 0) - (b.data.order ?? 0));
// Zufällig
posts.sort(() => Math.random() - 0.5);
TypeScript-Typen
Typen für Ihre Collections erzeugen:
npx emdash types
Erzeugt .emdash/types.ts mit Interfaces pro Collection:
import { getEmDashCollection, getEmDashEntry } from "emdash";
import type { Post } from "../.emdash/types";
const { entries: posts } = await getEmDashCollection<Post>("posts");
const { entry: post } = await getEmDashEntry<Post>("posts", "my-post");
Statisch vs. Server-Rendering
EmDash-Inhalte funktionieren statisch und serverseitig.
Statisch (Prerender)
Mit getStaticPaths Routen zur Build-Zeit:
---
import { getEmDashCollection, getEmDashEntry } from "emdash";
export async function getStaticPaths() {
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
return posts.map((post) => ({
params: { slug: post.data.slug },
}));
}
const { slug } = Astro.params;
const { entry: post } = await getEmDashEntry("posts", slug);
---
Server-Rendering
Für SSR direkt abfragen:
---
export const prerender = false;
import { getEmDashEntry } from "emdash";
const { slug } = Astro.params;
const { entry: post, error } = await getEmDashEntry("posts", slug);
if (error) {
return new Response("Server error", { status: 500 });
}
if (!post) {
return new Response(null, { status: 404 });
}
---
Performance
Caching
EmDash nutzt Astros Live Content Collections mit automatischem Caching. Bei SSR optional HTTP-Cache-Header:
---
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
Astro.response.headers.set("Cache-Control", "public, max-age=300");
---
Doppelte Abfragen vermeiden
Einmal abfragen und an Komponenten weitergeben:
---
import { getEmDashCollection } from "emdash";
import PostList from "../components/PostList.astro";
import Sidebar from "../components/Sidebar.astro";
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
const featured = posts.filter((p) => p.data.featured);
const recent = posts.slice(0, 5);
---
<PostList posts={featured} />
<Sidebar posts={recent} />
Nächste Schritte
- Create a Blog — Vollständigen Blog aufbauen
- Taxonomies — Nach Kategorien und Tags filtern
- Working with Content — Admin-CRUD
- Internationalization — Mehrsprachigkeit