Die Webentwicklung hat sich seit den Anfängen der statischen, einseitigen persönlichen Websites stark weiterentwickelt. Heute können wir aus einer Vielzahl von Sprachen, Frameworks und Content-Management-Systemen wählen, die für jede erdenkliche Nische entwickelt wurden.

Hier kommt Astro ins Spiel, eines der neuesten cool Kids auf dem JavaScript-Framework-Block.

Astro wurde von Fred K. Schott und einer Gruppe von Mitwirkenden entwickelt und hat sich schnell zu einem Favoriten in der Entwicklergemeinschaft entwickelt. Es ist ein All-in-One-Framework, das ähnlich wie ein statischer Website-Generator funktioniert.

In diesem Artikel erklären wir, warum so viele Entwickler Astro schätzen und es anderen Lösungen vorziehen. Außerdem zeigen wir dir, wie du mit dem Framework einen Markdown-basierten Blog erstellen kannst.

Was ist Astro?

Das Astro-Logo in Schwarz, das
Astro

Astro, oder Astro.js, ist ein beliebter Generator für statische Websites, der für diejenigen konzipiert wurde, die inhaltsreiche Websites erstellen wollen, die schnell und reibungslos funktionieren. Sein geringes Gewicht, seine intuitive Struktur und seine leichte Erlernbarkeit machen ihn für Entwickler aller Erfahrungsstufen attraktiv.

Trotz seines geringen Platzbedarfs verfügt Astro über leistungsstarke Tools, die die Flexibilität deiner Website drastisch erhöhen und dir viel Zeit bei der Verwaltung von Inhalten und Themes sparen. Darüber hinaus haben Entwickler die Möglichkeit, mit ihren bevorzugten Frameworks in Verbindung mit Astro zu arbeiten – eine attraktive Perspektive für erfahrene Programmierer, die bereits eine Reihe von Favoriten haben.

Hier sind nur einige der Möglichkeiten, mit denen sich Astro von der Masse abhebt:

  • Inselarchitektur: Astro zerlegt deine Benutzeroberfläche (UI) in kleinere, isolierte Komponenten, die so genannten „Astro-Inseln“, die auf jeder Seite verwendet werden können. Nicht benötigtes JavaScript wird durch schlankes HTML ersetzt.
  • Zero JavaScript (standardmäßig): Du kannst zwar so viel JavaScript verwenden, wie du willst, um deine Websites zu erstellen, aber Astro versucht, null JavaScript in der Produktion einzusetzen, indem es deinen Code für dich umschreibt. Dies ist der perfekte Ansatz, wenn dein Fokus auf der Geschwindigkeit deiner Website liegt.
  • SSG und SSR inklusive: Astro begann als statischer Website-Generator, aber im Laufe der Zeit wurde es zu einem Framework, das sowohl statische Website-Generierung (SSG) als auch serverseitiges Rendering (SSR) nutzt. Und du kannst auswählen, welche Seiten welchen Ansatz verwenden sollen.
  • Framework-agnostisch: Wenn du Astro verwendest, kannst du jedes JavaScript-Framework nutzen, das du möchtest – sogar mehrere Frameworks gleichzeitig. (Darauf gehen wir später in diesem Artikel noch genauer ein.)

Außerdem ist Astro „edge-ready“, das heißt, es kann jederzeit und überall problemlos eingesetzt werden.

Bist du bereit, mehr zu erfahren? Dann lass uns genauer untersuchen, wie Astro funktioniert.

Die Struktur von Astro

Bevor wir uns weiter vorwagen, ist es wichtig zu verstehen, wie Astro aufgebaut ist, damit du es effektiv nutzen kannst. Werfen wir einen Blick auf die grundlegende Dateistruktur von Astro:

├── dist/
├── src/
│   ├── components/
│   ├── layouts/
│   └── pages/
│       └── index.astro
├── public/
└── package.json

Wie du siehst, ist die Struktur selbst recht einfach. Dennoch gibt es einige wichtige Punkte, die du dir merken solltest:

  • Der größte Teil unseres Projekts befindet sich im Ordner src. Du kannst deine Komponenten, Layouts und Seiten in Unterordnern anordnen. Du kannst weitere Ordner hinzufügen, um dein Projekt übersichtlicher zu gestalten.
  • Der Ordner public enthält alle Dateien, die außerhalb des Erstellungsprozesses liegen, z. B. Schriftarten, Bilder oder eine robots.txt-Datei.
  • Der Ordner dist enthält alle Inhalte, die du auf deinem Produktionsserver bereitstellen willst.

Als Nächstes wollen wir uns die Hauptbestandteile von Astro genauer ansehen: Komponenten, Layouts und Seiten.

Komponenten

Komponenten sind wiederverwendbare Code-Bausteine, die du überall auf deiner Website einbauen kannst, ähnlich wie Shortcodes in WordPress. Standardmäßig haben sie die Dateierweiterung .astro, aber du kannst auch Komponenten verwenden, die nicht mit Astro, sondern mit Vue, React, Preact oder Svelte erstellt wurden.

Im Folgenden siehst du ein Beispiel dafür, wie eine einfache Komponente aussieht – in diesem Fall ein klassifizierter div Tag, der ein h2 enthält:


<div class="kinsta_component">
    <h2>Hello, Kinsta!</h2>
</div>

Und hier sehen wir, wie wir diese Komponente in unsere Website einbinden können:

---
import KinstaComponent from ../components/Kinsta.astro
---
<div>
    <KinstaComponent />
</div>

Wie oben gezeigt, musst du die Komponente zunächst importieren. Erst dann kann sie in die Seite eingebunden werden.

Jetzt ist es an der Zeit, unserer Komponente einige Eigenschaften hinzuzufügen. Beginnen wir mit der Eigenschaft {title}:

---
const { title = 'Hello' } = Astro.props
---

<div class="kinsta_component">
    <h2>{title}</h2>
</div>

Und so würde unsere Eigenschaft implementiert werden:

---
import KinstaComponent from ../components/Kinsta.astro
---

<div>
    
    <KinstaComponent title="Good day"/>

    
    <KinstaComponent />
 </div>

Ganz einfach, oder?

Wie du wahrscheinlich schon gemerkt hast, liegt die wahre Stärke der Astro-Komponenten in ihrer globalen und wiederverwendbaren Natur. Sie ermöglichen es dir, mit nur wenigen Zeilen Code umfassende Änderungen an deiner gesamten Website vorzunehmen, was dir unzählige Stunden ersparen kann, die du sonst mit mühsamen Texterneuerungen verbringen müsstest.

Layouts

Lass uns jetzt über Layouts sprechen. Neben ihrer bekannten thematischen Funktion sind Layouts in Astro auch wiederverwendbare Komponenten, aber sie werden als Code-Wrapper eingesetzt.

Sieh dir dieses Beispiel an:

---
// src/layouts/Base.astro
const { pageTitle = 'Hello world' } = Astro.props
---

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width">
    <title>{pageTitle}</title>
</head>
<body>
    <main>
        <slot />
    </main>
</body>
</html>

Beachte hier den <slot /> Tag. Das Element <slot /> dient in Astro als Platzhalter für die eigentlichen HTML-Tags und Inhalte.

Schauen wir es uns in Aktion an.

Der folgende Code zeigt, wie unser <slot /> Tag durch den gewünschten Code ersetzt wird, der von unserem Base.astro Layout umschlossen wird:

---
import Base from '../layouts/Base.astro';
---

<Base title="Hello world">
    <div>
        <p>Some example text.</p>
    </div>
</Base>

Wie du sehen kannst, wurde unser <slot /> Tag durch den HTML-Code ersetzt, den es darstellt:

<div>
    <p>Some example text.</p>
</div>

Wie du siehst, kannst du mit Layouts, genau wie mit Komponenten, Teile des Codes auf deiner gesamten Website wiederverwenden, was die Aktualisierung deines globalen Inhalts und Designs vereinfacht.

Seiten

Seiten sind eine besondere Art von Komponenten, die für das Routing, das Laden von Daten und die Erstellung von Vorlagen zuständig sind.

Astro verwendet ein dateibasiertes Routing, um Seiten zu erstellen, und kein dynamisches Routing. Die dateibasierte Methode verbraucht nicht nur weniger Bandbreite, sondern erspart dir auch den manuellen Import deiner Komponenten.

Hier ist ein Beispiel für definierte Routen:

src/pages/index.astro => yourdomain.com
src/pages/test.astro => domain.com/test
src/pages/test/subpage => domain.com/test/subpage

Mit diesen Routen würde unsere resultierende Homepage wie folgt gerendert werden:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width">
    <title>Hello World</title>
</head>
<body>
    <h1>Hello, Kinsta</h1>
</body>
</html>

Aber wir wissen bereits, wie man Layouts verwendet, also lass uns das in etwas umwandeln, das global zugänglich ist:

---
import Base from '../layouts/Base.astro';
---

<Base>
    <h1>Hello, Kinsta</h1>
</Base>

So – das ist viel sauberer.

Auf das Routing in Astro werden wir später in diesem Artikel noch genauer eingehen, aber jetzt wollen wir uns erst einmal dem eigentlichen Thema widmen: dem Aufbau und der Anpassung von Websites.

Anpassen und Erweitern von Astro

Es ist an der Zeit zu lernen, wie du deine Astro-Site anpasst! Wir werden Markdown-Sammlungen, Routing, Bildbearbeitung und eine Integration mit React nutzen, um unsere statische Website zu erstellen und zu personalisieren.

Markdown-Sammlungen

Mit der Version 2.0 hat Astro eine viel bessere Möglichkeit eingeführt, Markdown-Inhalte zu pflegen als zuvor. Dank der Sammlungen können wir sicher sein, dass alle unsere Frontmatter-Daten enthalten sind und die richtige Art der Verknüpfung haben.

Seit der Version 2.5 können auch JSON- und YAML-Dateien als Collections verwaltet werden.

Bist du bereit, dir die Hände schmutzig zu machen?

Lege zunächst alle deine Markdown-Artikel im Ordner src/content/collection_name ab. Wir werden für dieses Projekt eine Blog-Sammlung erstellen, also wird der Ordner in unserer Demonstration src/content/blog heißen.

Nun ist es an der Zeit, alle erforderlichen Frontmatter-Felder in unserer Datei src/content/config.ts zu definieren. Unser Blog benötigt die folgenden Angaben:

  • title (string)
  • tags (Array)
  • publishDate (Zeit)
  • image (String, optional)

So sieht das Ganze zusammengesetzt aus:

import { z, defineCollection } from 'astro:content';

const blogCollection = defineCollection({ 
    schema: z.object({
        title: z.string(),
        tags: z.array(z.string()),
        image: z.string().optional(),
        publishDate: z.date(),
    }),
});

export const collections = {
    'blog': blogCollection,
};

Und so sieht unsere Markdown-Datei article-about-astro.md aus:

---
title: Article about Astro
tags: [tag1, tag3]
publishDate: 2023-03-01
---
## Tamen risit

Lorem *markdownum flumina*, laceraret quodcumque Pachyne, **alter** enim
cadavera choro.

Zugegeben, es gibt nichts Besonderes an unserer Markdown-Datei. Aber es gibt hier eine versteckte Magie, die sich zeigt, wenn wir einen Tippfehler machen.

Nehmen wir zum Beispiel an, dass wir statt publishDate versehentlich publishData getippt haben. Im Falle eines solchen Schreibfehlers gibt Astro eine Fehlermeldung aus:

blog → article-about-astro.md frontmatter does not match collection schema.
  "publishDate" is required.

Erstaunlich, oder? Mit dieser raffinierten Funktion können wir in Sekundenschnelle Fehler in Bezug auf das Frontmatter finden.

Als Letztes müssen wir eine Seite hinzufügen, die unsere Daten anzeigt. Dazu erstellen wir eine Datei unter src/page/blog/[slug].astro mit dem folgenden Code:

---
import Base from '../../layouts/Base.astro';
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
    const blogEntries = await getCollection('blog');
    return blogEntries.map(entry => ({
        params: { slug: entry.slug }, props: { entry },
  }));
}
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<Base>
    <h1>{entry.data.title} </h1>
    <Content />
</Base>

Dank getStaticPaths wird Astro alle statischen Seiten für jeden Beitrag in der Blog-Sammlung erstellen.

Das Einzige, was uns jetzt noch fehlt, ist eine Auflistung aller unserer Artikel:

---
import Base from '../../layouts/Base.astro';

import { getCollection } from 'astro:content';
const blogEntries = await getCollection('blog');
---
<Base>
<ul>
    {blogEntries.map(item => <li> <strong><a href={'/blog/' + item.slug}>{item.data.title}</a></strong></li>)}
</ul>
</Base>

Wie du siehst, macht die Verwendung von Sammlungen diese Aufgabe bemerkenswert einfach.

Jetzt wollen wir eine Datentypsammlung erstellen. Zuerst müssen wir die Datei src/content/config.ts erneut öffnen und eine neue Datensammlung hinzufügen:

import { z, defineCollection, referenece } from 'astro:content';

const blogCollection = defineCollection({ 
	type: 'content',
    schema: z.object({
        title: z.string(),
        tags: z.array(z.string()),
        image: z.string().optional(),
        publishDate: z.date(),
	    author: reference('authors')
    }),
});

const authorsCollection = defineCollection({ 
	type: 'data',
    schema: z.object({
        fullName: z.string(),
        country: z.string()
    }),
});


export const collections = {
    'blog': blogCollection,
'authors': authorsCollection,
};

Wir haben nicht nur eine neue Sammlung angelegt, sondern auch die Autorenreferenz in der blogCollection hinzugefügt.

Zeit, einen neuen Autor zu erstellen. Wir müssen eine Datei namens maciek-palmowski.json in der content/authors.json erstellen:

{
    "fullName": "Maciek Palmowski",
    "country": "Poland"
}

Als Letztes müssen wir diese Daten in unserem Post abrufen. Dazu müssen wir getEntry verwenden:

---
import Base from '../../layouts/Base.astro';
import { getCollection, getEntry } from 'astro:content';
export async function getStaticPaths() {
  const blogEntries = await getCollection('blog');
  return blogEntries.map(entry => ({
    params: { slug: entry.slug }, props: { entry },
  }));
}
const { entry } = Astro.props;
const author = await getEntry(entry.data.author);
const { Content } = await entry.render();
---
<Base>
<h1>{entry.data.title}</h1>
<h2>Author: {author.data.fullName}</h2>
<Content />
</Base>

Routing

Astro hat zwei verschiedene Routing-Modi. Den ersten – das statische (dateibasierte) Routing – haben wir bereits kennengelernt, als wir die Seiten behandelt haben.

Jetzt werden wir uns auf das dynamische Routing konzentrieren.

Mit dynamischen Routing-Parametern kannst du eine Astro-Seitendatei anweisen, mehrere Seiten mit der gleichen Struktur automatisch zu erstellen. Das ist nützlich, wenn du viele Seiten eines bestimmten Typs hast (z. B. Autorenbiografien, Benutzerprofile, Dokumentationsartikel usw.).

In unserem nächsten Beispiel werden wir Bioseiten für unsere Autoren erstellen.

Im standardmäßigen statischen Ausgabemodus von Astro werden diese Seiten zum Zeitpunkt der Erstellung erzeugt, d.h. du musst die Liste der Autoren, die eine entsprechende Datei erhalten, vorher festlegen. Im dynamischen Modus hingegen werden die Seiten auf Anfrage für jede Route erstellt, die übereinstimmt.

Wenn du eine Variable als Dateinamen übergeben willst, füge sie in Klammern hinzu:

pages/blog/[slug].astro -> blog/test, blog/about-me 

Lass uns das anhand des Codes aus unserer src/page/blog/[slug] -Datei genauer betrachten:

---
import Base from '../../layouts/Base.astro';
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
    const blogEntries = await getCollection('blog');
    return blogEntries.map(entry => ({
        params: { slug: entry.slug }, props: { entry },
  }));
}
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<Base>
    <h1>{entry.data.title}</h1>
    <Content />
</Base>

Die getStaticPaths Route ist für die Erstellung aller statischen Seiten verantwortlich. Sie gibt zwei Objekte zurück:

  • params: Sie wird verwendet, um die Klammern in unseren URLs zu füllen
  • props: Alle Werte, die wir an die Seite übergeben

Und damit ist die Seitenerstellung erledigt.

Umgang mit Bildern

Wir können nicht über performante Websites sprechen, ohne moderne Bildformate, korrekte Methoden zur Größenanpassung und Lazy Loading zu erwähnen.

Zum Glück hat Astro auch hier für uns gesorgt. Dank des Pakets @astrojs/image können wir all diese Dinge in wenigen Minuten einführen.

Nach der Installation des Pakets erhalten wir Zugang zu zwei Komponenten: Image und Picture.

Die Komponente Image wird verwendet, um einen optimierten <img /> Tag zu erstellen. Hier ist ein Beispiel:

---
import { Image } from '@astrojs/image/components';
import heroImage from '../assets/hero.png';
---

<Image src={heroImage} format="avif" alt="descriptive text" />
<Image src={heroImage} width={300} alt="descriptive text" />
<Image src={heroImage} width={300} height={600} alt="descriptive text" />

Mit der Komponente Picture wird eine optimierte <picture/> Komponente erstellt:

---
import { Picture } from '@astrojs/image/components';
import hero from '../assets/hero.png';
---
<Picture src={hero} widths={[200, 400, 800]} sizes="(max-width: 800px) 100vw, 800px" alt="descriptive text" />

SSG vs. SSR

Standardmäßig läuft Astro als statischer Website-Generator. Das bedeutet, dass der gesamte Inhalt in statische HTML-Seiten umgewandelt wird.

Obwohl dies in vielerlei Hinsicht ein perfekter Ansatz ist (vor allem in Bezug auf die Geschwindigkeit), würden wir manchmal einen dynamischeren Ansatz vorziehen. Wenn du z. B. für jeden Nutzer eine eigene Profilseite haben möchtest oder wenn du Tausende von Artikeln auf deiner Seite hast, wäre es viel zu zeitaufwändig, alles jedes Mal neu zu rendern.

Glücklicherweise kann Astro auch als vollständig serverseitig gerendertes Framework oder in einem Hybridmodus zwischen beiden arbeiten.

Um seitenweite SSR zu aktivieren, müssen wir den folgenden Code in astro.config.mjs einfügen:

import { defineConfig } from 'astro/config';

export default defineConfig({
    output: 'server'
});

Dies ist der Standardansatz.

Der hybride Ansatz bedeutet, dass standardmäßig alles dynamisch generiert wird, mit Ausnahme der Seiten, denen export const prerender = true hinzugefügt wurde.

Mit Astro 2.5 gibt es auch die Möglichkeit, statisches Rendering als Standard einzustellen und dynamische Routen manuell auszuwählen.

Damit können wir zum Beispiel eine vollständig statisch generierte Website mit dynamischen Login- und Profilseiten erstellen. Toll, oder?

Mehr darüber kannst du in der offiziellen Dokumentation nachlesen.

Andere JavaScript-Frameworks einbinden

Eine weitere tolle Funktion von Astro ermöglicht es dir, dein Lieblingsframework mitzubringen und es zusammen mit Astro zu verwenden. Du kannst Astro mit React, Preact, Svelte, Vue, Solid oder Alpine kombinieren (alle Integrationen findest du in der Astro-Dokumentation „Integrationen hinzufügen“).

Nehmen wir an, wir wollen React verwenden. Als Erstes müssen wir die Integration installieren, indem wir Folgendes in npm ausführen:

npx astro add react

Jetzt, wo React integriert ist, können wir eine React-Komponente erstellen. In unserem Fall wird es die Zählerkomponente unter src/components/ReactCounter.tsx sein:

import { useState } from 'react';

/** A counter written with React */
export function Counter({ children }) {
    const [count, setCount] = useState(0);
    const add = () => setCount((i) => i + 1);
    const subtract = () => setCount((i) => i - 1);

    return (
        <>
            <div className="counter">
                <button onClick={subtract}>-</button>
                <pre>{count}</pre>
                <button onClick={add}>+</button>
                </div>
            <div className="counter-message">{children}</div>
        </>
    );
}

Zu guter Letzt müssen wir den Zähler mit folgendem Code auf unserer Seite platzieren:

---
import * as react from '../components/ReactCounter';
---
<main>
    <react.Counter client:visible />
</main>

Und voilà: Deine React-Komponente ist nahtlos in deine Seite integriert.

Wie man Astro mit Kinsta einsetzt

Jetzt ist es an der Zeit, unsere Astro-Website ins Netz zu stellen. Zum Glück ist Kinsta der perfekte Hoster für eine schnelle und problemlose Bereitstellung.

Beginne damit, ein GitHub-Repository für die Dateien deiner Website zu erstellen. Wenn du noch nicht bereit bist, deine eigenen Dateien zu verwenden, kannst du die von unserem Team erstellte Vorlage für die Astro-Startseite klonen.

Ein Teil des GitHub-Repos für die Astro-Startseite von Kinsta zeigt ein Bild des weißen Astro-
GitHub-Repository der Astro-Startseite von Kinsta

Sobald dein Repository fertig ist, melde dich bei MyKinsta an, wähle links Anwendungen aus und wähle dann Anwendung aus dem lila Dropdown-Menü Dienst hinzufügen.

Das MyKinsta-Dashboard öffnete sich im Bereich
Eine Anwendung in MyKinsta hinzufügen

Im letzten Schritt gibst du Kinsta die Details deines Builds und deiner Bereitstellung bekannt.

Auf die meisten Fragen, wie z. B. Prozessname und Zahlungsmethode, gibt es eindeutige oder einfache Antworten. Beachte, dass du das Feld Startbefehl leer lassen kannst, wenn du willst; Kinsta wird dann automatisch npm start als Befehl zuweisen.

Wenn du dir unsicher bist, wie du auf andere Fragen antworten sollst, findest du in der Kinsta-Dokumentation feldspezifische Anleitungen und Beispiele für die Bereitstellung von Astro. Du kannst dir auch die Astro-Anleitung für den Einsatz bei Kinsta ansehen.

Wenn du die Details deines Builds eingegeben hast, klicke auf die Schaltfläche Zahlungsmethode bestätigen, um dein Build zu initialisieren.

Und das war’s! Du hast jetzt eine voll funktionsfähige statische Website, die mit dem Astro-Framework erstellt wurde.

Eine dunkle Seite mit dem Kinsta-Logo in Weiß in der Mitte über den Worten
Unsere Live-Astro-Startseite

Du findest deine Live-URL und andere Einsatzdetails unter Einsätze in deinem MyKinsta-Konto.

Der Bildschirm
Ein erfolgreiche Astro-Bereitstellung

Zusammenfassung

Die klare Struktur, die einfache Syntax und die globalen Komponenten von Astro machen das Erstellen und Betreiben einer Anwendung wirklich einfach. Seine Leichtgewichtigkeit und die doppelte Nutzung von statischem und dynamischem Routing erhöhen die Reaktionsfähigkeit der Website erheblich, während seine Fähigkeit, mit anderen JavaScript-Frameworks zu kooperieren, es für erfahrene Programmierer noch attraktiver macht.

Wenn es dein Ziel ist, eine inhaltsreiche Website zu erstellen, die schnell lädt, modulare Funktionen bietet und sowohl statisch als auch dynamisch generiert werden kann, dann könnte Astro die richtige Wahl für dich sein.

Du kannst deine statische Website mit dem Anwendungs-Hosting von Kinsta kostenlos hosten und wenn sie dir gefällt, kannst du auf unseren Hobby Tier Plan upgraden .

Was denkst du über den Astro Generator für statische Websites? Hast du ihn schon für ein eigenes Projekt verwendet? Lass es uns in den Kommentaren unten wissen.

Maciek Palmowski

Maciek ist Webentwickler und arbeitet bei Kinsta als Development Advocate Analyst. Nach Feierabend verbringt er die meiste Zeit damit, zu programmieren, nach interessanten Neuigkeiten für seine Newsletter zu suchen oder Kaffee zu trinken.