Serverseitiges Rendern (SSR)

Serverseitiges Rendern, auch bekannt als SSR, kann in Astro aktiviert werden. Wenn du SSR aktivierst, kannst du:

  • Sitzungen f√ľr den Anmeldestatus in deiner Anwendung implementieren.
  • Daten von einer API rendern, die dynamisch mit fetch abgerufen werden.
  • Deine Webseite auf einem Host mithilfe eines Adapters bereitstellen.

Um SSR zu aktivieren, musst du einen Adapter verwenden. Das liegt daran, dass SSR eine Server-Laufzeitumgebung ben√∂tigt: Die Umgebung, in der dein serverseitiger Code ausgef√ľhrt wird. Diese Laufzeitumgebung bietet eine API, die der serverseitige Code nutzen kann.

Durch die Installation eines Adapters erh√§lt Astro Zugriff auf die entsprechende API und kann ein Skript ausgeben, das dein Projekt auf diesem Server ausf√ľhrt.

Die folgenden Adapter sind aktuell verf√ľgbar, weitere werden in Zukunft folgen:

Unter den oben genannten Links zu den einzelnen Adaptern kannst du Anleitungen f√ľr die folgenden beiden Schritte (unter Verwendung von mein-adapter als Beispielplatzhalter) finden, um SSR zu aktivieren.

  1. Installiere den Adapter in deine Projektabhängigkeiten via npm oder dem Paketmanager deiner Wahl:

    Terminal-Fenster
    npm install --save-dev @astrojs/mein-adapter
  2. F√ľge den Adapter¬†(EN) zum Import und Standard-Export deiner astro.config.mjs-Datei hinzu:

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import meinAdapter from '@astrojs/mein-adapter';
    export default defineConfig({
    output: 'server',
    adapter: meinAdapter(),
    });

Astro bleibt standardm√§√üig ein Generator f√ľr statische Websites. Sobald du jedoch einen Adapter f√ľr serverseitiges Rendern aktivierst, wird jede Route in deinem pages-Verzeichnis zu einer serverseitig gerenderten Route und es stehen dir einige neue Funktionen zur Verf√ľgung.

Die Header der Anfrage sind verf√ľgbar unter Astro.request.headers. Dies ist ein Headers-Objekt, ein Map-√§hnliches Objekt, √ľber das du Header (z.B. einen Cookie) abrufen kannst.

src/pages/index.astro
---
const cookie = Astro.request.headers.get('cookie');
// ...
---
<html>
<!-- Hier ist die Seite... -->
</html>

Diese Funktion des globalen Astro-Objekts erm√∂glicht es dir, auf eine andere Seite umzuleiten. Du k√∂nntest dies machen, nachdem du √ľberpr√ľft hast, ob der Nutzer angemeldet ist, indem du seine Sitzung aus einem Cookie abrufst.

src/pages/account.astro
---
import { isLoggedIn } from '../utils';
const cookie = Astro.request.headers.get('cookie');
// Wenn der Nutzer nicht angemeldet ist, leite ihn zur Anmeldeseite weiter
if (!isLoggedIn(cookie)) {
return Astro.redirect('/login');
}
---
<html>
<!-- Hier ist die Seite... -->
</html>

Du kannst auch eine Response von deiner Seite zur√ľckgeben. Dies k√∂nntest machen, um auf einer dynamischen Seite 404 zur√ľckzugeben, nachdem du eine id in der Datenbank √ľberpr√ľft hast.

src/pages/[id].astro
---
import { getProduct } from '../api';
const product = await getProduct(Astro.params.id);
// Kein Produkt gefunden
if (!product) {
return new Response(null, {
status: 404,
statusText: 'Nicht vorhanden'
});
}
---
<html>
<!-- Hier ist die Seite... -->
</html>

Eine API-Route ist eine .js- oder .ts-Datei im src/pages-Verzeichnis, die einen Request entgegennimmt und eine Response zur√ľckgibt. Es ist eine m√§chtige F√§higkeit von SSR, dass API-Routen sicher Code auf der Serverseite ausf√ľhren k√∂nnen.

In Astro werden diese Routen zu serverseitig gerenderten Routen, was dir erlaubt, Funktionen zu nutzen, die zuvor auf der Clientseite nicht verf√ľgbar waren, oder die explizite Abfragen eines Backend-Servers und zus√§tzlichen clientseitigen Code zum Rendern der Ergebnisse erforderten.

Im folgenden Beispiel wird eine API-Route verwendet, um ein Produkt aus einer Datenbank abzurufen, ohne dass eine Seite f√ľr jede dieser Optionen erstellt werden muss.

src/pages/[id].js
import { getProduct } from '../db';
export async function get({ params }) {
const { id } = params;
const product = await getProduct(id);
if (!product) {
return new Response(null, {
status: 404,
statusText: 'Nicht vorhanden'
});
}
return new Response(JSON.stringify(product), {
status: 200
});
}

In diesem Beispiel kann ein g√ľltiger HTML-Code zur√ľckgegeben werden, um die gesamte Seite oder einen Teil ihres Inhalts auszugeben.

Neben dem Abrufen von Inhalten und dem serverseitigen Rendern k√∂nnen API-Routen als REST-API-Endpunkte verwendet werden, um Funktionen wie Authentifizierungen, Datenbankzugriffe und √úberpr√ľfungen auszuf√ľhren, ohne dass sensible Daten f√ľr den Client sichtbar werden.

Im folgenden Beispiel wird eine API-Route verwendet, um Google reCaptcha v3 zu verifizieren, ohne dass der √∂ffentliche Schl√ľssel an die Clients weitergegeben wird.

src/pages/index.astro
<html>
<head>
<script src="https://www.google.com/recaptcha/api.js"></script>
</head>
<body>
<button class="g-recaptcha"
data-sitekey="√ĖFFENTLICHER_SCHL√úSSEL"
data-callback="onSubmit"
data-action="submit"> Klick auf mich, um die Captcha-Herausforderung zu √ľberpr√ľfen! </button>
<script is:inline>
function onSubmit(token) {
fetch("/recaptcha", {
method: "POST",
body: JSON.stringify({ recaptcha: token })
})
.then((response) => response.json())
.then((gResponse) => {
if (gResponse.success) {
// Captcha-Verifizierung war erfolgreich
} else {
// Captcha-Verifizierung fehlgeschlagen
}
})
}
</script>
</body>
</html>

In der API-Route kannst du sichere private Schl√ľssel eingeben oder deine geheimen Umgebungsvariablen lesen.

src/pages/recaptcha.js
import fetch from 'node-fetch';
export async function post({ request }) {
const data = request.json();
const recaptchaURL = 'https://www.google.com/recaptcha/api/siteverify';
const requestBody = {
secret: "DEIN_PRIVATER_WEBSITE_SCHL√úSSEL", // Dies kann eine Umgebungsvariable sein
response: data.recaptcha // Das vom Client √ľbermittelte Token
};
const response = await fetch(recaptchaURL, {
method: "POST",
body: JSON.stringify(requestBody)
});
const responseData = await response.json();
return new Response(JSON.stringify(responseData), { status: 200 });
}