Webentwicklung · Rendering · Nachschlagewerk

Rendering Strategien

Ein vollständiges Nachschlagewerk zu SPA, SSR, SSG, ISR und klassischem PHP – mit Request-Flows, Datenbasis, Node-Anforderungen, Frameworks und Entscheidungshilfe.

SPA SSR SSG ISR PHP
SPA

Single Page Application

Rendering vollständig im Browser – der Server liefert nur ein leeres HTML-Gerüst + JS-Bundle.

Kernprinzip: Der Server liefert eine fast leere index.html mit einem JavaScript-Bundle. Der Browser lädt dieses Bundle, und Vue/React baut das komplette HTML im Browser auf. Alle Daten werden zur Laufzeit per API-Call vom Browser geholt. Der Server ist passiv – er versteht die App nicht, er liefert nur Dateien aus.
Request / Response Flow
BrowserURL eingeben
HTTP GET
File Server / CDNstatische Dateien
leeres HTML + JS
Browserrendert alles selbst
JS im Browsernach Bundle-Load
fetch()
API / BackendREST, GraphQL
JSON
Browserrendert UI mit Daten

// Kein HTML vom Server – der Browser baut alles auf. Kein Hydration-Schritt nötig.

Datenbasis

Vollständig dynamisch

Alle Daten werden zur Laufzeit per API-Call geholt. Die App kennt beim Build keine Inhalte – alles kommt vom Backend während der Nutzer die Seite besucht.

Node-Prozess

Nicht erforderlich

Das fertige dist/-Verzeichnis sind reine statische Dateien. Apache, Nginx oder ein CDN reichen vollständig aus. Node nur nötig wenn eine eigene API gebaut wird – das ist aber eine separate Entscheidung.

Hydration

Nicht vorhanden

Es gibt kein server-gerendertes HTML das "aktiviert" werden muss. Das JS übernimmt von Anfang an die volle Kontrolle und baut den DOM komplett auf.

✓ Kein laufender Node-Prozess zur Laufzeit erforderlich

Vorteile

  • Reiches, reaktives UI/UX-Erlebnis
  • Kein Server zur Laufzeit nötig
  • Einfachstes Hosting – jeder Webserver
  • Schnelle Navigation nach Initial-Load
  • Backend-Technologie frei wählbar
  • Ideal für Auth-geschützte Bereiche

Nachteile

  • Schlechtes SEO (leeres HTML für Crawler)
  • Langsames Initial-Load (JS muss erst laden)
  • Kein serverseitiger State möglich
  • Daten erst sichtbar nach JS-Ausführung
  • Schlechte Performance auf schwachen Geräten

SEO

Schlecht

Initial-Speed (FCP)

Langsam

Interaktivität

Exzellent

Hosting-Kosten

Minimal

Datenaktualität

Immer aktuell

Frameworks & Build-Befehl
# Vue 3 + Vite (Standard SPA)
npm create vue@latest my-app
cd my-app && npm install
npm run build        # → dist/ → auf beliebigen Webserver hochladen

# React + Vite
npm create vite@latest my-app -- --template react
Dashboards Admin-Tools Web-Apps hinter Login PWAs Interne Tools Konfiguratoren
SSR

Server-Side Rendering

Rendering auf dem Server bei jedem eingehenden Request – fertiges HTML sofort an den Browser.

Kernprinzip: Bei jedem HTTP-Request rendert ein Node-Server die Vue/React-Komponenten zu fertigem HTML – inklusive der aktuellen Daten aus DB oder API. Der Browser empfängt sofort darstellbares HTML (gut für SEO und FCP), danach wird das JS-Bundle nachgeladen und die Seite "hydriert" – also interaktiv gemacht. Das ist der entscheidende Unterschied zu klassischem PHP: PHP kennt kein Hydration-Konzept.
Request / Response Flow
BrowserRequest
HTTP GET
Node ServerNuxt / Next.js
DB-Query
DB / APIeigen od. extern
DB / APIDaten zurück
JSON
Node Serverrendert Komponenten
fertiges HTML
Browserzeigt sofort Inhalt
Browsernach HTML-Empfang
JS laden
HydrationJS aktiviert Vue/React
interaktiv
Fertige Appreaktiv & SEO-freundlich

// Jeder Request trifft den Node-Server. Kein Caching = immer frische Daten.

Datenbasis

Vollständig dynamisch

Der Server liest DB oder API bei jedem Request. Nutzerspezifische, zeitkritische oder personalisierte Inhalte sind problemlos möglich. Kein Build nötig nach Datenänderungen.

Node-Prozess

Zwingend erforderlich

Ein dauerhaft laufender Node-Prozess (z.B. via PM2) ist nicht optional. Der Server muss JavaScript verstehen um Vue/React-Komponenten rendern zu können. Apache/Nginx allein reichen nicht.

Hydration

Ja – nach HTML-Empfang

Browser empfängt fertiges HTML, lädt danach das JS-Bundle nach. Vue/React "erkennt" das HTML wieder und aktiviert Event-Handler und Reaktivität. Seite ist kurz darstellbar aber nicht interaktiv (TTI > FCP).

✕ Node-Prozess dauerhaft erforderlich (PM2, Docker, etc.)

Vorteile

  • Sehr gutes SEO – vollständiges HTML für Crawler
  • Schnelles FCP (First Contentful Paint)
  • Immer aktuelle Daten
  • Nutzerspezifischer Content möglich
  • Keine Sichtbarkeit von API-Keys im Client

Nachteile

  • Node-Server dauerhaft erforderlich
  • Höhere Serverkosten als SSG/SPA
  • Skalierung komplexer
  • Latenz pro Request (DB-Query-Zeit)
  • Hydration-Mismatch kann zu Bugs führen

SEO

Sehr gut

Initial-Speed (FCP)

Mittel

Datenaktualität

Immer aktuell

Hosting-Kosten

Hoch

Nutzer-spezifisch

Ja – pro Request

Nuxt 3 – SSR Konfiguration (Standard)
// nuxt.config.ts
export default defineNuxtConfig({
  ssr: true,  // Standard in Nuxt 3

  routeRules: {
    '/dashboard/**': { ssr: false },  // SPA für Auth-Bereich
    '/api/**':        { cors: true }
  }
})

// Server starten via PM2
pm2 start "node .output/server/index.mjs" --name my-app
E-Commerce Personalisierter Content Social Feeds Buchungsplattformen Live-Daten-Portale Headless-CMS-Frontends
PHP

Klassisches PHP (Server-Side Rendering ohne Hydration)

Der Ursprung von SSR: HTML wird bei jedem Request direkt auf dem Server erzeugt – ganz ohne JS-Framework, Build-Schritt oder Hydration.

Kernprinzip: Bei jedem Request führt der Webserver (Apache/Nginx via PHP-FPM oder mod_php) das PHP-Skript aus, holt Daten aus der DB und gibt fertiges HTML zurück – ohne separaten Node-Prozess und ohne Client-seitiges Framework. Es gibt kein Hydration-Konzept, weil kein virtuelles DOM im Browser "übernehmen" muss: das HTML ist von Anfang an das fertige Ergebnis. Jede Navigation ist ein klassischer Full-Page-Reload (Multi-Page Application, kurz MPA) – der historische Gegenpol zu SPA/SSR-mit-Hydration, aber weiterhin die Basis von WordPress, Shopware, Laravel- oder Symfony-Anwendungen und damit dem Großteil des Webs.
Request / Response Flow
BrowserRequest
HTTP GET
Apache / Nginx+ PHP-FPM
DB-Query
MySQL / MariaDBklassisches RDBMS
DBDaten zurück
PHP rendert Template
PHP-ProzessBlade, Twig, echo/HTML
fertiges HTML
Browserzeigt sofort & ist sofort interaktiv

// Kein Hydration-Schritt, kein JS-Bundle nötig – das HTML ist von Anfang an das fertige, interaktive Ergebnis.

Datenbasis

Vollständig dynamisch

Wie SSR: die DB wird bei jedem Request live abgefragt. Personalisierte, nutzerspezifische oder zeitkritische Inhalte sind der Standardfall, kein Build nötig nach Datenänderungen.

Node-Prozess

Nicht erforderlich

Statt eines Node-Prozesses übernimmt PHP-FPM (oder mod_php) die Ausführung. Läuft auf jedem klassischen LAMP-/LEMP-Stack – ideal für Shared Hosting und Plesk-Setups ohne Node/PM2.

Hydration

Existiert nicht

Es gibt keinen Client-seitigen Zustand, den ein Framework "übernehmen" müsste. Interaktivität entsteht klassisch über Formulare, Links und optional isoliertes Vanilla-JS/jQuery – kein Hydration-Mismatch möglich.

✓ Kein Node-Prozess erforderlich (PHP-FPM statt Node)

Vorteile

  • Sehr gutes SEO – vollständiges HTML sofort
  • Sofort interaktiv, kein Hydration-Delay
  • Kein Node/PM2 nötig – klassisches Shared Hosting reicht
  • Riesiges Ökosystem (WordPress, Laravel, Symfony, Shopware)
  • Sehr niedrige Einstiegshürde, breite Hosting-Verfügbarkeit
  • Nutzerspezifischer Content ohne Zusatzaufwand

Nachteile

  • Kein reaktives UI ohne zusätzliches JS
  • Full-Page-Reload bei jeder Navigation
  • Latenz pro Request (PHP-Ausführung + DB-Query)
  • Kein Component-Sharing zwischen Server/Client wie bei SSR-Frameworks
  • Skalierung meist vertikal (mehr PHP-Worker) statt CDN-Edge

SEO

Sehr gut

Initial-Speed (FCP)

Schnell (kein JS-Bundle nötig)

Datenaktualität

Immer aktuell

Hosting-Kosten

Niedrig (Standard-Webhosting)

Nutzer-spezifisch

Ja – pro Request

Klassisches PHP – Beispiel & PHP-FPM-Anbindung
// index.php – Daten holen und direkt als HTML ausgeben
<?php
$stmt = $pdo->query('SELECT title, body FROM posts ORDER BY id DESC');
?>
<ul>
<?php foreach ($stmt as $post): ?>
  <li><?= htmlspecialchars($post['title']) ?></li>
<?php endforeach; ?>
</ul>

# Nginx – Anbindung an PHP-FPM (kein Node nötig)
location ~ \.php$ {
    fastcgi_pass unix:/run/php/php8.5-fpm.sock;
}
WordPress / CMS Laravel / Symfony Shopware / WooCommerce Klassische Firmenwebseiten Shared Hosting / Plesk Intranets ohne JS-Build
SSG

Static Site Generation

Alle Seiten werden einmalig beim Build als statische HTML-Dateien erzeugt. Kein Laufzeit-Server.

Kernprinzip: Beim Build-Prozess werden alle Seiten als vollständige HTML-Dateien vorgerendert. Daten werden einmalig aus CMS, DB oder API gezogen und in das HTML eingebakken. Das Ergebnis ist ein Ordner mit statischen Dateien der auf jedem Webserver oder CDN liegt – ohne Node-Prozess, ohne Datenbankzugriff zur Laufzeit. Inhaltsänderungen erfordern einen neuen Build.
Build-Phase (einmalig beim Deployment)
Build Toolnuxt generate / vite
Daten holen
CMS / DB / APIDatenquelle
JSON
Build Toolrendert Seiten
output
dist/HTML, CSS, JS
Laufzeit (jeder Besucher – kein Server-Prozess)
BrowserRequest
HTTP GET
CDN / Nginxstatisch ausliefern
fertiges HTML
Browsersofort sichtbar
JS laden
Hydrationoptional

// Kein DB-Zugriff zur Laufzeit. Kein Node-Prozess. Maximale Performance.

Datenbasis

Statisch (Stand: letzter Build)

Daten werden einmalig beim Build aus CMS, DB oder API gezogen. Zur Laufzeit gibt es keinen DB-Zugriff. Ändert sich der Content, muss neu gebaut werden – manuell oder via CI/CD-Webhook.

Node-Prozess

Nur während des Builds

Node läuft ausschließlich beim Build. Das Ergebnis sind statische Dateien die auf Apache, Nginx, Plesk, S3 oder einem CDN liegen. Kein PM2, kein dauerhafter Prozess auf dem Server nötig.

Deployment

Einfachstes Deployment

Build lokal oder in CI/CD (GitHub Actions, etc.) erzeugen, dist/-Ordner auf den Webserver laden. Deployment ist identisch zu einer statischen HTML-Seite – für Plesk-Setups ideal.

✓ Kein Node-Prozess zur Laufzeit – nur während des Builds

Vorteile

  • Maximale Performance – vorgerendertes HTML
  • CDN-auslieferbar, kein Laufzeit-Server
  • Bestes SEO – vollständiges HTML sofort
  • Sehr günstig zu hosten
  • Einfachstes Deployment
  • Kein Single Point of Failure (Server)

Nachteile

  • Kein dynamischer / nutzerspezifischer Content
  • Rebuild nötig bei jeder Inhaltsänderung
  • Langsamer Build bei sehr vielen Seiten
  • Kein Echtzeit-Content möglich
  • Nicht geeignet für Auth-geschützte Inhalte

SEO

Exzellent

Initial-Speed (FCP)

Sehr schnell

Datenaktualität

Stand: letzter Build

Hosting-Kosten

Minimal

Nutzer-spezifisch

Nein

Nuxt 3 – SSG generieren
// nuxt.config.ts
export default defineNuxtConfig({
  ssr: true,

  routeRules: {
    '/**': { prerender: true }  // alle Routen statisch
  }
})

# Build ausführen
npx nuxi generate
# → .output/public/ = statische Dateien → auf Webserver hochladen

# VitePress (Docs)
npx vitepress build docs
Dokumentation Blogs Portfolios Landingpages Marketing-Seiten Firmenpräsentationen
ISR

Incremental Static Regeneration

Statisch wie SSG, aber mit automatischer Hintergrund-Regeneration nach einem TTL-Intervall.

Kernprinzip: ISR ist ein Hybrid aus SSG und SSR. Seiten werden statisch gebaut und schnell ausgeliefert (wie SSG). Nach Ablauf eines konfigurierten TTL-Timers wird die Seite im Hintergrund regeneriert – ohne dass ein Full-Rebuild nötig ist. Der erste Besucher nach TTL-Ablauf bekommt noch die alte Version, triggert aber die Regeneration. Der nächste Besucher sieht schon die frische Seite. Das nennt sich stale-while-revalidate.
stale-while-revalidate Prinzip (TTL = 60s)
Buildt=0
Seite v1gecacht
Besucher A (t=30s)
bekommt v1sofort
TTL abgelaufent=65s
Besucher B triggert
bekommt v1noch alt
+
Hintergrundregeneriert v2
Seite v2jetzt gecacht
Besucher C (t=70s)
bekommt v2frisch

// Node-Server läuft dauerhaft im Hintergrund für die Regeneration.

Datenbasis

Statisch mit TTL-Revalidierung

Daten werden beim Build und nach TTL-Ablauf aus DB/API neu gezogen. Kleine Verzögerung (je nach TTL) ist tolerierbar. Nicht geeignet für Echtzeit- oder nutzerspezifische Daten.

Node-Prozess

Zwingend erforderlich

Obwohl die Seiten gecacht wirken – ein Node-Server läuft im Hintergrund und übernimmt die Revalidierung. Kein laufender Prozess = kein ISR. Oft vergessen weil es sich wie SSG anfühlt.

On-Demand ISR

Auch möglich

Statt TTL-Intervall kann Regeneration auch on-demand via Webhook getriggert werden – z.B. wenn ein CMS-Eintrag gespeichert wird. Nuxt 3 und Next.js unterstützen beide Varianten.

✕ Node-Prozess dauerhaft erforderlich (Regeneration im Hintergrund)

Vorteile

  • Statisch schnell – gecachtes HTML
  • Automatische Aktualisierung ohne Rebuild
  • CDN-kompatibel
  • Gutes SEO
  • Günstigere Serverkosten als reines SSR
  • On-Demand Revalidierung via Webhook möglich

Nachteile

  • Erster Besucher nach TTL sieht veraltete Version
  • Node-Server trotzdem erforderlich
  • Kein nutzerspezifischer Content
  • Komplexere Logik als reines SSG
  • TTL-Konfiguration erfordert Überlegung

SEO

Sehr gut

Initial-Speed (FCP)

Sehr schnell

Datenaktualität

Nach TTL-Ablauf

Hosting-Kosten

Niedrig–mittel

Nutzer-spezifisch

Nein

Nuxt 3 – ISR via routeRules
// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/products/**': { isr: 3600 },    // jede Stunde regenerieren
    '/news/**':     { isr: 300 },     // alle 5 Minuten
    '/about':       { prerender: true }, // reines SSG
    '/dashboard':   { ssr: false }     // SPA
  }
})

// Next.js (Pages Router)
export async function getStaticProps() {
  return { props: { data }, revalidate: 60 } // 60s TTL
}
Produkt-Kataloge News-Portale Preisseiten Immobilien-Listings Semi-dynamischer Content

Vollständiger Vergleich

Alle vier Ansätze auf einen Blick.

Kriterium SPA SSR PHP (klassisch) SSG ISR
Rendering-Ort Browser Server (pro Request) Server (pro Request) Build-Zeit Build + Hintergrund
Node-Prozess ✓ Nein ✕ Ja, zwingend ✓ Nein (PHP-FPM) ✓ Nur beim Build ✕ Ja, zwingend
SEO Schlecht Sehr gut Sehr gut Exzellent Sehr gut
Initial-Speed (FCP) Langsam Mittel Schnell Sehr schnell Sehr schnell
Datenaktualität Immer aktuell Immer aktuell Immer aktuell Stand: letzter Build Nach TTL-Ablauf
Nutzer-spezifisch Ja Ja Ja Nein Nein
Hosting-Kosten Minimal Hoch Niedrig Minimal Niedrig–mittel
Hydration Nein Ja – nach HTML-Empfang Existiert nicht Ja – optional Ja – nach HTML-Empfang
Rebuild bei Änderung Nein Nein Nein Ja – zwingend Nein – auto TTL
Datenbasis API (runtime) DB/API (runtime) DB/API (runtime) DB/API (build) DB/API (build + TTL)
Hosting Statisch / CDN Node-Server Apache/Nginx + PHP-FPM Statisch / CDN Node-Server + CDN
Frameworks Vue + Vite, React + Vite Nuxt 3, Next.js, SvelteKit WordPress, Laravel, Symfony VitePress, Nuxt generate, Astro Next.js, Nuxt 3 (routeRules), Astro
Verhältnis zu PHP Kein Äquivalent Wie PHP, plus Hydration/JS-Framework Referenzpunkt – der Ursprung von SSR Kein Äquivalent Kein Äquivalent

Entscheidungshilfe

Welcher Ansatz für welches Projekt?

Welchen Modus brauche ich?

Ist die Seite hinter einem Login / braucht keinen SEO?
Dashboards, Admin-Tools, interne Apps, Web-Apps mit Authentifizierung
SPA
Vue + Vite
Sind Inhalte nutzerspezifisch oder in Echtzeit nötig?
Personalisierter Feed, Live-Preise, Session-abhängige Daten
SSR
Nuxt 3 / Next.js
Brauchst du serverseitig aktuelle Daten, aber kein JS-Framework/Hydration?
CMS, Shop, klassische Web-Anwendung, Standard-Webhosting ohne Node
PHP (klassisch)
Laravel / Symfony / WordPress
Ändern sich Inhalte sehr selten und ist maximale Performance gewünscht?
Blog, Doku, Portfolio, Landingpage, Firmenseite
SSG
VitePress / Nuxt generate
Ändern sich Inhalte regelmäßig, kleine Verzögerung ist aber OK?
Produktkatalog, News, Preislisten – aktuell aber nicht Echtzeit
ISR
Nuxt routeRules / Next.js
Großes Projekt mit verschiedenen Anforderungen pro Route?
Startseite SSG, Produktseiten ISR, Dashboard SPA, Checkout SSR
Nuxt 3 Hybrid
routeRules mixen
Hinweis für Plesk-Setups: SPA und SSG sind deployment-technisch identisch zu einer statischen HTML-Seite – dist/-Ordner hochladen, fertig. Kein PM2, kein nvm auf dem Server. SSR und ISR erfordern einen laufenden Node-Prozess der auf einem dedizierten Port läuft – typischerweise via PM2 mit Nginx als Reverse Proxy davor.