Zum Inhalt springen

Optional: Erstelle eine Content-Collection

Nun, da du einen Blog mit Astros integrierter dateibasierter Routenführung (EN) hast, wirst du ihn so aktualisieren, dass es eine Content-Collection (Inhaltssammlung) (EN) verwendet. Content-Collections sind eine leistungsstarke Möglichkeit, Gruppen ähnlicher Inhalte – etwa Blogbeiträge – zu verwalten.

Mach dich bereit, …

  • deinen Ordner mit Blogbeiträgen nach src/blog/ zu verschieben
  • ein Schema zu erstellen, um das Frontmatter deiner Blogbeiträge zu definieren
  • getCollection() zu verwenden, um Inhalte und Metadaten der Blogbeiträge abzurufen

Auch wenn du Content-Collections verwendest, nutzt du weiterhin den Ordner src/pages/ für einzelne Seiten, etwa deine „Über mich“-Seite. Wenn du jedoch deine Blogbeiträge aus diesem speziellen Ordner herausnimmst, kannst du leistungsfähigere APIs nutzen, um dein Blog-Index und einzelne Beiträge zu erzeugen und anzuzeigen.

Gleichzeitig erhältst du in deinem Code-Editor bessere Vorschläge und Autovervollständigung, da du ein Schema (EN) hast, das eine gemeinsame Struktur für jeden Beitrag definiert. Astro hilft dir, diese Struktur mithilfe von Zod, einer Schema- und Validierungs­bibliothek für TypeScript, durchzusetzen.
In deinem Schema kannst du festlegen, welche Frontmatter-Eigenschaften erforderlich sind – etwa description oder author – und welchen Datentyp jede Eigenschaft haben muss, z. B. string oder array. So fängst du viele Fehler frühzeitig ab, mit klaren Fehlermeldungen, die genau erklären, was schiefgelaufen ist.

Lies mehr über Astros Content-Collections (EN) in unserer Anleitung, oder folge den Schritten unten, um ein einfaches Blog von src/pages/posts/ nach src/blog/ umzuwandeln.

  1. Welche Art von Seite würdest du wahrscheinlich in src/pages/ behalten?

  2. Welcher Punkt ist kein Vorteil davon, Blogbeiträge in eine Content-Collection zu verschieben?

  3. Content-Collections verwenden TypeScript …

Die folgenden Schritte zeigen dir, wie du das Endergebnis des Blog-Tutorials erweiterst, indem du eine Content-Collection für deine Blogbeiträge erstellst.

Aktualisiere Astro und alle Integrationen auf die neuesten Versionen, indem du im Terminal die folgenden Befehle ausführst:

Terminal-Fenster
# Astro und offizielle Integrationen gemeinsam aktualisieren
npx @astrojs/upgrade

Ein Content-Collection für deine Beiträge erstellen

Abschnitt betitelt „Ein Content-Collection für deine Beiträge erstellen“
  1. Erstelle eine neue Collection (einen Ordner) namens src/blog/.

  2. Verschiebe alle bestehenden Blogbeiträge (.md-Dateien) von src/pages/posts/ in diesen neuen Ordner.

  3. Erstelle eine Datei src/content.config.ts, um ein Schema zu definieren (EN) für deine postsCollection. Für den bestehenden Code aus dem Blog-Tutorial füge Folgendes in die Datei ein, um alle im Frontmatter verwendeten Eigenschaften zu definieren:

    src/content.config.ts
    import { glob } from "astro/loaders";
    import { z, defineCollection } from "astro:content";
    const blog = defineCollection({
    loader: glob({ pattern: '**/[^_]*.md', base: "./src/blog" }),
    schema: z.object({
    title: z.string(),
    pubDate: z.date(),
    description: z.string(),
    author: z.string(),
    image: z.object({
    url: z.string(),
    alt: z.string()
    }),
    tags: z.array(z.string())
    })
    });
    export const collections = { blog };
  4. Damit Astro dein Schema erkennt, beende (Strg + C/Control + C) und starte den Entwicklungs­server neu. Dadurch wird das Modul astro:content bereitgestellt.

  1. Erstelle eine neue Seiten­datei src/pages/posts/[...slug].astro.
    Markdown- und MDX-Dateien werden innerhalb einer Sammlung nicht mehr automatisch zu Seiten. Du musst daher eine Seite erstellen, die für die Ausgabe jedes einzelnen Blogbeitrags verantwortlich ist.

  2. Füge den folgenden Code ein, um deine Sammlung abzufragen (EN) und für jede generierte Seite die slug und den Seiteninhalt bereitzustellen:

    src/pages/posts/[...slug].astro
    ---
    import { getCollection, render } from 'astro:content';
    export async function getStaticPaths() {
    const posts = await getCollection('blog');
    return posts.map(post => ({
    params: { slug: post.id }, props: { post },
    }));
    }
    const { post } = Astro.props;
    const { Content } = await render(post);
    ---
  3. Gib <Content /> innerhalb deines Markdown-Layouts aus, um ein gemeinsames Layout für alle Beiträge zu verwenden.

    src/pages/posts/[...slug].astro
    ---
    import { getCollection, render } from 'astro:content';
    import MarkdownPostLayout from '../../layouts/MarkdownPostLayout.astro';
    export async function getStaticPaths() {
    const posts = await getCollection('blog');
    return posts.map(post => ({
    params: { slug: post.id }, props: { post },
    }));
    }
    const { post } = Astro.props;
    const { Content } = await render(post);
    ---
    <MarkdownPostLayout frontmatter={post.data}>
    <Content />
    </MarkdownPostLayout>
  4. Entferne die layout-Eigenschaft aus dem Frontmatter jedes einzelnen Beitrags.
    Dein Inhalt wird nun beim Rendern in ein Layout eingebettet, diese Angabe ist also nicht mehr nötig.

  1. Überall dort, wo du eine Liste von Blogbeiträgen hast – z. B. auf der Blogseite src/pages/blog.astro – musst du import.meta.glob() durch getCollection() (EN) ersetzen, um Inhalte und Metadaten aus deinen Markdown-Dateien abzurufen.

  2. Passe anschließend alle Verweise auf die zurückgegebenen Daten an:
    Die Frontmatter-Werte befinden sich jetzt unter der Eigenschaft data. Außerdem hat jedes post-Objekt nun eine slug statt einer vollständigen URL.

Falls nötig, aktualisiere Frontmatter-Werte in deinem Projekt, etwa in Layouts, damit sie deinem Schema entsprechen.
Im Blog-Tutorial war pubDate ursprünglich ein String. Laut Schema ist es jetzt ein Date-Objekt. Dadurch kannst du Methoden wie toLocaleDateString() verwenden, um das Datum zu formatieren:

src/layouts/MarkdownPostLayout.astro
<!-- ... -->
<BaseLayout pageTitle={frontmatter.title}>
<p>{frontmatter.pubDate.toLocaleDateString()}</p>
<p><em>{frontmatter.description}</em></p>
<p>Autor/Autorin: {frontmatter.author}</p>
<img src={frontmatter.image.url} width="300" alt={frontmatter.image.alt} />
<!-- ... -->

Das Blog-Tutorial enthält einen RSS-Feed.
Diese Funktion muss ebenfalls getCollection() verwenden, um die Beiträge abzurufen und deren data-Objekt zu nutzen:

src/pages/rss.xml.js
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
export async function GET(context) {
const posts = await getCollection("blog");
return rss({
title: 'Astro-Lernender | Blog',
description: 'Mein Weg mit Astro',
site: context.site,
items: posts.map((post) => ({
title: post.data.title,
pubDate: post.data.pubDate,
description: post.data.description,
link: `/posts/${post.id}/`,
})),
customData: `<language>de-de</language>`,
});
}

Das vollständige Beispiel des Blog-Tutorials mit Content-Collections findest du im Content-Collections-Branch des Tutorial-Repos.

Wirke mit Community Sponsor