Zum Inhalt springen

Routing

Astro verwendet dateibasiertes Routing, um URLs aus der Struktur an Dateien und Verzeichnissen zu erzeugen, die du in deinem Projekt unter src/pages/ anlegst. Wenn eine Datei zum src/pages-Verzeichnis deines Projekts hinzugefügt wird, ist sie basierend auf ihrem Dateinamen automatisch als Route erreichbar.

Astro-Komponenten (.astro) und Markdown-Dateien (.md) im Verzeichnis src/pages werden automatisch zu Seiten auf deiner Website. Die Route jeder Seite entspricht ihrem Pfad und Dateinamen im Verzeichnis src/pages.

# Beispiel: Statische Routen
src/pages/index.astro -> meineseite.de/
src/pages/ueber.astro -> meineseite.de/ueber
src/pages/ueber/index.astro -> meineseite.de/ueber
src/pages/ueber/mich.astro -> meineseite.de/ueber/mich
src/pages/posts/1.md -> meineseite.de/posts/1

Astro verwendet standardmäßige <a>-HTML-Elemente, um zwischen einzelnen Routen zu navigieren. Es gibt keine Framework-spezifische <Link>-Komponente.

src/pages/index.astro
<p>Erfahre mehr <a href="/about/">über</a> Astro!</p>

Mit Astro kannst du aus einer einzelnen Seiten-Komponente mehrere Routen erzeugen, die einem bestimmten Kriterium entsprechen, indem du dynamische Routenparameter in ihrem Datei- oder Verzeichnisnamen verwendest. Du kannst so mehrere verwandte Seiten auf einmal erstellen, z. B. eine Seite für jeden Autor oder jedes Schlagwort deines Blogs. Hierbei unterstützt Astro sowohl “benannte Parameter”, mit denen du mögliche Werte für eine einzelne Verzeichnisebene angeben kannst, als auch “Rest-Parameter”, die flexiblere “Catch-all”-Routen mit beliebiger Verzeichnistiefe ermöglichen.

Astro-Seiten, die dynamische Routen erzeugen, müssen folgende Kriterien erfüllen:

  1. Sie müssen einen oder mehrere dynamische Parameter in [eckigen Klammern] im Datei- oder Verzeichnisnamen enthalten.

  2. Sie müssen eine getStaticPaths()-Funktion exportieren, die genau angibt, welche Routen von Astro vorgerendert werden sollen.

Du kannst Routen mit einem [benannten] Parameter generieren, indem du in deiner getStaticPaths()-Funktion die zu verwendenden Werte wie folgt zur Verfügung stellst:

src/pages/hunde/[hund].astro
---
export function getStaticPaths() {
return [
// Generiert: /hunde/rocky
{params: {hund: 'rocky'}},
// Generiert: /hunde/luna
{params: {hund: 'luna'}},
// Generiert: /hunde/rex
{params: {hund: 'rex'}},
];
}
---

📚 Erfahre mehr über getStaticPaths().

Routen können aus mehreren benannten Parametern auf jeder Ebene des Dateipfads generiert werden:

  • pages/blog/[slug].astro → (/blog/hallo-welt, /blog/beitrag-2 usw.)
  • pages/[benutzername]/settings.astro → (/fred/settings, /andreas/settings usw.)
  • pages/[sprache]-[version]/info.astro → (/en-v1/info, /fr-v2/info usw.)

Astro-Komponenten, die Routen dynamisch generieren, haben Zugriff auf ein Astro.params-Objekt für jede Route. Dadurch kannst du diese generierten Teile der URL in deinem Komponentenskript und deiner Vorlage verwenden.

src/pages/posts/[id].astro
---
const { id } = Astro.params;
---
<p>Beitrag: {id}</p>
// Astro.params-Objekt für die Route `/post/abc`
{ "id": "abc" }

Mehrere dynamische Routensegmente können auf die gleiche Weise kombiniert werden.

src/pages/post/[id]/[comment].astro
---
const { id, comment } = Astro.params;
---
// Astro.params-Objekt für die Route `/post/abc/ein-kommentar`
{ "id": "abc", "comment": "ein-kommentar" }

Wenn du mehr Flexibilität beim URL-Routing benötigst, kannst du einen Rest-Parameter in deinem .astro-Dateinamen als universellen Auffangbehälter für Dateipfade beliebiger Tiefe verwenden, indem du drei Punkte (...) in deine Klammern einfügst.

Hier ein Beispiel:

  • pages/post/[...slug].astro → (/post/a, /post/a/b, /post/a/b/c usw.)

Die passenden Werte werden als Parameter (im Beispiel slug) an die Seite übergeben.

// Astro.params-Objekt für die Route `/post/a/b/c`
{ "slug": "a/b/c" }

Als praktisches Beispiel könntest du GitHub’s Dateibetrachter mit der folgenden Kombination aus benannten Parametern und Rest-Parametern implementieren:

/[org]/[repo]/tree/[branch]/[...file]

Ein Aufruf der URL /withastro/astro/tree/main/docs/public/favicon.svg würde in diesem Beispiel dazu führen, dass die folgenden Parameter auf der Seite verfügbar sind:

{
org: 'withastro',
repo: 'astro',
branch: 'main',
file: 'docs/public/favicon.svg'
}

Es ist möglich, dass mehrere Routen mit demselben URL-Pfad übereinstimmen. Zum Beispiel würde jede dieser Routen mit /posts/create übereinstimmen:

└── pages/
│ ├── posts/
│ │ ├── create.astro
│ │ ├── [pid].astro
│ │ └── [...slug].astro

Astro muss wissen, welche Route zum Erstellen der Seite verwendet werden soll. Dazu werden sie nach folgenden Regeln sortiert:

  • Statische Routen ohne Pfadparameter haben Vorrang vor allen anderen Routen
  • Dynamische Routen mit benannten Parametern haben Vorrang vor Rest-Parametern
  • Rest-Parameter haben die niedrigste Priorität
  • Bei Gleichstand wird alphabetisch sortiert

Hier noch einige Beispiele basierend auf der obenstehenden Dateistruktur, welche Astro-Dateien zur Erzeugung des HTML-Codes für welche angeforderten URLs verwendet werden:

  • pages/posts/create.astro - Erzeugt /posts/create
  • pages/posts/[pid].astro - Erzeugt /posts/1, /posts/abc usw., aber nicht /posts/create
  • pages/posts/[...slug].astro - Erzeugt /posts/1/2, /posts/a/b/c usw., aber nicht /posts/create, /posts/1 oder /posts/abc

Astro unterstützt von Haus aus das Aufteilen großer Datenmengen auf mehrere Seiten. Es werden dabei alle üblicherweise benötigten Eigenschaften generiert, einschließlich der URLs der vorherigen/nächsten Seite, der Gesamtzahl der Seiten und mehr.

Um eine Seitennummerierung zu einer Route hinzuzufügen, kannst du die gleiche Syntax mit [Klammern] wie bei einer standardmäßigen dynamischen Route verwenden. Beispielsweise kann der Dateiname /astronauten/[page].astro die Routen für /astronauten/1, /astronauten/2 usw. erzeugen, wobei [page] durch die generierte Seitennummer ersetzt wird.

Das folgende Beispiel zeigt, wie du die Funktion paginate() verwenden kannst, um diese Seiten für ein Array von Werten zu generieren:

src/pages/astronauten/[page].astro
---
export async function getStaticPaths({ paginate }) {
const astronauten = [{
astronaut: 'Neil Armstrong',
}, {
astronaut: 'Buzz Aldrin',
}, {
astronaut: 'Sally Ride',
}, {
astronaut: 'John Glenn',
}];
// Erzeuge Seiten aus unserem Astronauten-Array, mit 2 pro Seite
return paginate(astronauten, { pageSize: 2 });
}
// Alle generierten Paginierungs-Daten werden an die
// Eigenschaft "page" von Astro.props übergeben
const { page } = Astro.props;
---
<!-- Zeige die aktuelle Seitennummer an.
Astro.params.page kann auch verwendet werden! -->
<h1>Page {page.currentPage}</h1>
<ul>
<!-- Liste die auf dieser Seite enthaltenen Astronauten auf -->
{page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>

Dadurch werden die folgenden Seiten mit jeweils 2 Astronauten pro Seite erzeugt:

  • /astronauten/1 - Seite 1: Zeigt “Neil Armstrong” und “Buzz Aldrin” an
  • /astronauten/2 - Seite 2: Zeigt “Sally Ride” und “John Glenn” an

Wenn du die paginate()-Funktion verwendest, werden die erzeugten Daten jeder Seite über eine Eigenschaft namens page übergeben. Der Wert dieser page-Eigenschaft ist ein Objekt mit vielen nützlichen Untereigenschaften. Hier einige Highlights:

  • page.data - Ein Array aus den Elementen, die auf der aktuellen Seite enthalten sind (eine Teilmenge der von dir an die paginate()-Funktion übergebenen Elemente)
  • page.url.next - Ein Link zur nächsten Seite der Sammlung
  • page.url.prev - Ein Link zur vorherigen Seite der Sammlung
src/pages/astronauten/[page].astro
---
// Paginiere die gleiche Liste an { astronaut }-Objekten
// wie im vorherigen Beispiel
export async function getStaticPaths({ paginate }) { /* ... */ }
const { page } = Astro.props;
---
<h1>Seite {page.currentPage}</h1>
<ul>
{page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>
{page.url.prev ? <a href={page.url.prev}>Vorherige Seite</a> : null}
{page.url.next ? <a href={page.url.next}>Nächste Seite</a> : null}
interface Page<T = any> {
/** Teilmenge an Elementen auf der aktuellen Seite */
data: T[];
/** Metadaten */
/** Index des ersten Elements auf der Seite, beginnend mit 0 */
start: number;
/** Index des letzten Elements auf der Seite, beginnend mit 0 */
end: number;
/** Gesamtzahl der Elemente */
total: number;
/** Aktuelle Seitennummer, beginnend mit 1 */
currentPage: number;
/** Anzahl von Elementen pro Seite (Standard: 25) */
size: number;
/** Seitennummer der letzten Seite */
lastPage: number;
url: {
/** URL der aktuellen Seite */
current: string;
/** URL der vorherigen Seite (falls vorhanden) */
prev: string | undefined;
/** URL der nächsten Seite (falls vorhanden) */
next: string | undefined;
};
}

Ein fortgeschrittener Anwendungsfall ist die verschachtelte Paginierung. Dieser Fall tritt auf, wenn eine Paginierung mit anderen dynamischen Routenparametern kombiniert wird. Du kannst eine verschachtelte Paginierung verwenden, um deine paginierte Sammlung nach einer Eigenschaft oder einem Schlagwort zu gruppieren.

Wenn du z. B. deine paginierten Markdown-Beiträge nach einem Schlagwort gruppieren möchtest, kannst du eine verschachtelte Paginierung verwenden, indem du die Seite /src/pages/[tag]/[page].astro erstellst. Diese entspricht dann den folgenden URLs:

  • /rot/1 (tag=rot)
  • /rot/2 (tag=rot)
  • /blau/1 (tag=blau)
  • /gruen/1 (tag=gruen)

Verschachtelte Paginierung funktioniert, indem von der getStaticPaths()-Funktion jeweils ein Array von paginate()-Ergebnissen pro Gruppierung zurückgegeben wird.

Im folgenden Beispiel implementieren wir eine verschachtelte Paginierung, um die oben aufgeführten URLs zu erstellen:

src/pages/[tag]/[page].astro
---
export async function getStaticPaths({ paginate }) {
const allTags = ['rot', 'blau', 'gruen'];
const allPosts = await Astro.glob('../../posts/*.md');
// Erzeuge für jedes Schlagwort ("tag") ein paginate()-Ergebnis.
// Achte darauf, `{params: {tag}}` an `paginate()` zu übergeben,
// damit Astro weiß, für welche Schlagwort-Gruppe ("tag")
// das jeweilige Ergebnis verwendet wird.
return allTags.map((tag) => {
const filteredPosts = allPosts.filter((post) => post.frontmatter.tag === tag);
return paginate(filteredPosts, {
params: { tag },
pageSize: 10
});
});
}
const { page } = Astro.props;
const params = Astro.params;