TL;DR: SEO für Single-Page-Applications beginnt mit einer unbequemen Wahrheit: SPAs machen es Suchmaschinen standardmäßig schwer. Google steckt JavaScript-Seiten zunächst in eine Rendering-Warteschlange — ein Prozess, der Stunden bis Tage dauern kann, und AI-Crawler wie GPTBot, ClaudeBot und PerplexityBot führen JavaScript überhaupt nicht aus. Die Lösung ist serverseitiges Rendering mit Next.js, Nuxt, Angular SSR oder SvelteKit. Dieser Leitfaden zeigt dir die genaue Einrichtung für jedes Framework — inklusive Code, Testschritten und der Rendering-Realität 2026.
Single-Page-Applications laden ein einziges HTML-Grundgerüst und füllen es dann mit JavaScript. Für Nutzer fühlt sich das schnell und app-ähnlich an. Für Googlebot kommt oft erst einmal nur ein leeres <div id="app"></div> an.


Ich habe über SEOJuice Hunderte SPAs auditiert. Das Muster wiederholt sich ständig: Die Website sieht im Browser großartig aus, JavaScript läuft perfekt, und Suchmaschinen sehen nichts. Oder schlimmer — sie sehen den Inhalt erst Tage später, nachdem die Seite in Googles Rendering-Warteschlange gelegen hat. Allein der Angular-Hash-URL-Bug hat Kunden mehr organischen Traffic gekostet als jedes Algorithmus-Update, an das ich mich erinnern kann. Ein E-Commerce-Kunde mit Angular und HashLocationStrategy hatte 1.200 Produktseiten. Google sah exakt eine Seite — die Startseite. Alles nach dem # war unsichtbar. Das ist kein kleiner Ranking-Dämpfer. Das sind 60% des organischen Umsatzes, einfach weg, wegen einer Routing-Konfiguration, die man in zwei Minuten beheben kann, wenn man weiß, wonach man suchen muss.
So funktioniert Googles Rendering-Pipeline tatsächlich:
Diese Rendering-Warteschlange zwischen Schritt 2 und Schritt 3? Sie kann wenige Sekunden oder mehrere Tage dauern. Deine Wettbewerber mit serverseitig gerendertem HTML überspringen diese Warteschlange komplett — ihr Inhalt wird schon beim ersten Crawling indexiert.
Und es wird noch ungemütlicher. 2025 hat Vercel mehr als eine Milliarde Crawler-Requests analysiert und festgestellt, dass die meisten AI-Crawler JavaScript überhaupt nicht ausführen. GPTBot, ClaudeBot, PerplexityBot — sie konsumieren rohes, ungerendertes HTML. Eine Analyse von über einer halben Milliarde GPTBot-Abrufen fand keinerlei Hinweise auf JavaScript-Ausführung. Wenn deine SPA auf clientseitiges Rendering angewiesen ist, ist dein Inhalt für die Crawler unsichtbar, die hinter ChatGPT, Claude und der Suche von Perplexity stehen.
"Wenn deine Next.js-Website kritische Seiten als JavaScript-abhängige SPAs ausliefert, sind diese Seiten für die Systeme unzugänglich, die prägen, wie Menschen Informationen entdecken."
Das ist kein Nischenproblem. Wenn du willst, dass dein Inhalt 2026 sowohl von Google als auch von AI-Suchmaschinen gefunden wird, ist serverseitiges Rendering nicht mehr optional — es ist Voraussetzung.
Es gibt vier Wege, eine Single-Page-Application zu rendern. Diese Entscheidung bestimmt, ob Suchmaschinen deinen Inhalt sofort, irgendwann oder nie sehen.
| Ansatz | Wie es funktioniert | SEO-Auswirkung | Time to First Byte (TTFB) | Am besten geeignet für |
|---|---|---|---|---|
| CSR (Client-Side Rendering) | Der Browser lädt ein leeres HTML-Grundgerüst herunter, JavaScript baut die Seite | Schlecht — Google steckt die Seite in die Rendering-Warteschlange, AI-Crawler sehen nichts | Schnell (aber leer) | Interne Dashboards, Admin-Panels, geschützte Seiten |
| SSR (Server-Side Rendering) | Der Server erzeugt pro Request vollständiges HTML und sendet die komplette Seite | Exzellent — vollständiger Inhalt schon beim ersten Crawling | Variabel (Server-Verarbeitungszeit) | Dynamische Inhalte: E-Commerce, News, nutzergenerierte Inhalte |
| SSG (Static Site Generation) | Seiten werden beim Deploy als statisches HTML vorab gebaut | Exzellent — schnellste Ladezeit, vollständig crawlbar | Am schnellsten (über CDN ausgeliefert) | Blogs, Dokumentation, Marketing-Seiten, Landingpages |
| ISR (Incremental Static Regeneration) | Statische Seiten, die zeitgesteuert oder bei Bedarf neu generiert werden | Exzellent — SSG-Geschwindigkeit mit frischem Inhalt | Schnell (gecacht mit Hintergrund-Rebuild) | Große Websites mit periodisch wechselnden Inhalten (Produktkataloge, Listings) |
Kernaussage
Jede Seite, die bei Google oder in AI-Suchmaschinen ranken soll, muss serverseitig gerendert oder vorgerendert sein. CSR ist okay für geschützte Seiten und Dashboards. Für alles, was öffentlich ist, nutze SSR, SSG oder ISR.
Die Regel ist simpel: Wenn eine URL in der Suche ranken soll, muss sie bereits in der ersten Serverantwort vollständiges HTML ausliefern. Keine Ausnahmen. Kein „aber Google rendert doch inzwischen JavaScript“. Google tut das — manchmal, irgendwann, unzuverlässig, und AI-Crawler versuchen es nicht einmal. Ich habe diese Diskussion mit Frontend-Entwicklern öfter geführt, als ich zählen kann. Das Gespräch endet meistens, wenn ich ihnen ihre Seite im URL-Prüftool von Google zeige und sie dort eine leere Seite sehen, wo eigentlich ihr wunderschönes UI sein sollte.
Normales React (Create React App, Vite mit React) ist nur CSR. Google hat damit Probleme. Next.js ist die Antwort — und seit der App Router in Next.js 13+ zum Standard geworden ist, ist Next.js aus SEO-Sicht deutlich besser geworden.
Mit dem App Router werden Komponenten standardmäßig auf dem Server gerendert. Du fügst 'use client' nur dann hinzu, wenn eine Komponente Browser-APIs oder Interaktivität braucht. Das bedeutet: Der Großteil deines Seiteninhalts wird als pures HTML ausgeliefert — ganz ohne JavaScript-Rendering.
// app/blog/[slug]/page.tsx — Server Component (default)
import { Metadata } from 'next'
// Dynamic metadata for each blog post
export async function generateMetadata({ params }): Promise<Metadata> {
const post = await getPost(params.slug)
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
type: 'article',
publishedTime: post.publishedAt,
},
alternates: {
canonical: `https://example.com/blog/${params.slug}`,
},
}
}
// This component runs on the server — zero JS shipped to the browser
export default async function BlogPost({ params }) {
const post = await getPost(params.slug)
return (
<article>
<h1>{post.title}</h1>
<div>{post.content}</div>
</article>
)
}
Für Inhalte, die sich nicht häufig ändern (Blogposts, Landingpages), solltest du die Seiten schon beim Build vorab rendern:
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await getAllPosts()
return posts.map((post) => ({ slug: post.slug }))
}
// Combined with the page component above,
// Next.js generates static HTML at build time for every post
Für E-Commerce-Seiten mit Tausenden Produkten nutzt du ISR, um Seiten nach Zeitplan neu zu validieren:
// app/products/[id]/page.tsx
export const revalidate = 3600 // Regenerate every hour
export default async function ProductPage({ params }) {
const product = await getProduct(params.id)
return <ProductDetail product={product} />
}
Wenn du in normalem React festhängst und nicht auf Next.js migrieren kannst, nutze als Zwischenlösung einen Pre-Rendering-Service wie Prerender.io. Aber mach dir nichts vor: Das ist Klebeband, keine echte Lösung. Jeder Monat, in dem du die Migration verschiebst, ist ein Monat mit suboptimaler Indexierung.
Gleiche Geschichte, anderes Ökosystem. Normales Vue mit Vue Router ist nur CSR. Nuxt 3 gibt dir SSR, SSG, ISR und Edge Rendering mit Nitro — alles in einem Framework.
Nuxt 3 nutzt Universal Rendering direkt out of the box. Keine Konfiguration nötig — deine Seiten werden beim ersten Laden serverseitig gerendert und danach für clientseitige Navigation hydratisiert.
<!-- pages/blog/[slug].vue -->
<script setup>
const route = useRoute()
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`)
// Per-page SEO metadata
useHead({
title: post.value.title,
meta: [
{ name: 'description', content: post.value.excerpt },
{ property: 'og:title', content: post.value.title },
{ property: 'og:description', content: post.value.excerpt },
],
link: [
{ rel: 'canonical', href: `https://example.com/blog/${route.params.slug}` }
]
})
</script>
<template>
<article>
<h1>{{ post.title }}</h1>
<div v-html="post.content" />
</article>
</template>
Mit routeRules in Nuxt 3 kannst du Rendering-Strategien innerhalb derselben App mischen. Das ist extrem nützlich für Websites mit statischen Marketing-Seiten und dynamischen Inhalten:
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true }, // SSG — homepage
'/blog/**': { isr: 3600 }, // ISR — blog posts regenerate hourly
'/products/**': { ssr: true }, // SSR — dynamic product pages
'/dashboard/**': { ssr: false }, // CSR — authenticated dashboard
}
})
Nitro, die Server-Engine von Nuxt 3, unterstützt Deployments auf Edge-Plattformen (Cloudflare Workers, Vercel Edge, Netlify Edge). Das bedeutet: Deine SSR-Seiten werden an CDN-Edge-Standorten gerendert, die dem Nutzer am nächsten sind — sub-50ms TTFB sind realistisch. Für SEO heißt das: schnellere Ladezeiten, bessere Core Web Vitals und häufigeres Crawling durch Google.
Angular war historisch eines der schwierigsten Frameworks, wenn es um SEO ging. Das hat sich seit Angular 17 deutlich geändert, weil SSR dort mit eingebauter Hydration-Unterstützung zum First-Class Citizen geworden ist. Kein nachträgliches Dranschrauben von Angular Universal mehr.
Neue Projekte bekommen SSR standardmäßig, wenn du die CLI verwendest:
# New project with SSR enabled
ng new my-app --ssr
# Add SSR to an existing project
ng add @angular/ssr
// product-page.component.ts
import { Component, OnInit } from '@angular/core';
import { Meta, Title } from '@angular/platform-browser';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-product-page',
template: `
<article>
<h1>{{ product.name }}</h1>
<p>{{ product.description }}</p>
</article>
`
})
export class ProductPageComponent implements OnInit {
product: any;
constructor(
private meta: Meta,
private title: Title,
private route: ActivatedRoute,
private productService: ProductService
) {}
ngOnInit() {
const id = this.route.snapshot.paramMap.get('id');
this.productService.getProduct(id).subscribe(product => {
this.product = product;
this.title.setTitle(product.name);
this.meta.updateTag({ name: 'description', content: product.description });
this.meta.updateTag({ property: 'og:title', content: product.name });
});
}
}
Angular 19.2 hat Incremental Hydration eingeführt, aufbauend auf der @defer-API. Komponenten rendern vollständiges HTML auf dem Server, werden aber erst im Client hydratisiert, wenn ein Trigger ausgelöst wird (im Viewport, bei Interaktion usw.). Das reduziert das JavaScript, das an den Browser ausgeliefert wird, während für Crawler weiterhin vollständiger SSR-Inhalt verfügbar bleibt.
Angular-spezifischer Stolperstein
Hash-basiertes Routing (HashLocationStrategy) erzeugt URLs wie example.com/#/products. Google ignoriert alles nach dem #. Dein 500-Seiten-Produktkatalog sieht aus wie eine einzige Seite. Wechsle sofort zu PathLocationStrategy — das ist in Angular standardmäßig aktiv, aber einige Legacy-Projekte nutzen immer noch Hash-Routing. Genau dieser Bug hat den E-Commerce-Kunden von oben 60% seines organischen Traffics gekostet. Sie liefen zwei Jahre lang mit Hash-Routing. Zwei Jahre Produktseiten, von denen Google nie wusste, dass sie existieren. Der Fix dauerte 20 Minuten. Die Erholung dauerte vier Monate.
SvelteKit hat sich still und leise zu einem der besten Frameworks für SEO out of the box entwickelt. SSR ist standardmäßig aktiviert — du müsstest es aktiv abschalten. Das Framework kompiliert sich praktisch selbst weg und liefert deutlich weniger JavaScript aus als React oder Angular.
Jede SvelteKit-Seite wird standardmäßig serverseitig gerendert. Deine +page.svelte-Dateien erzeugen beim ersten Request vollständiges HTML:
<!-- src/routes/blog/[slug]/+page.svelte -->
<script>
export let data;
</script>
<svelte:head>
<title>{data.post.title}</title>
<meta name="description" content={data.post.excerpt} />
<link rel="canonical" href={`https://example.com/blog/${data.post.slug}`} />
</svelte:head>
<article>
<h1>{data.post.title}</h1>
{@html data.post.content}
</article>
// src/routes/blog/[slug]/+page.server.ts
export async function load({ params }) {
const post = await getPost(params.slug);
return { post };
}
Wie Nuxt erlaubt dir auch SvelteKit, das Rendering pro Route zu steuern:
// src/routes/blog/[slug]/+page.ts
export const prerender = true; // SSG — generate at build time
// src/routes/dashboard/+page.ts
export const ssr = false; // CSR-only for authenticated content
Warum SvelteKit für SEO Aufmerksamkeit verdient: Der Compiler eliminiert die Framework-Runtime. Eine SvelteKit-Seite liefert nur einen Bruchteil des JavaScript aus, das eine vergleichbare Next.js- oder Nuxt-Seite braucht. Weniger JavaScript bedeutet schnelleres LCP, bessere INP-Werte und glücklichere Core Web Vitals — alles Ranking-Signale.
Jede SPA sollte diese Checks bestehen. Nach Wirkung sortiert — behebe zuerst die Punkte ganz oben.
| # | Check | Warum das wichtig ist | So behebst du es |
|---|---|---|---|
| 1 | SSR oder SSG für alle öffentlichen Seiten aktiviert | Ohne das steckt Google deine Seiten in die Rendering-Warteschlange und AI-Crawler sehen nichts | Next.js App Router, Nuxt 3, Angular SSR oder SvelteKit |
| 2 | Saubere URLs (keine Hash-Fragmente) | Hash-URLs (#/page) sind für Suchmaschinen unsichtbar | Nutze history-basiertes Routing — Standard in allen modernen Frameworks |
| 3 | Eindeutiger Title-Tag pro Seite | Der gleiche Title auf jeder Route führt dazu, dass Google eine Version auswählt und den Rest ignoriert | generateMetadata (Next.js), useHead() (Nuxt), Meta-Service (Angular), <svelte:head> |
| 4 | Eindeutige Meta Description pro Seite | Steuert dein Snippet in den Suchergebnissen | Dieselben Libraries wie für Title-Tags — pro Route setzen |
| 5 | Canonical-Tags auf jeder Seite | Verhindert Duplicate-Content-Probleme durch Query-Parameter und Trailing Slashes | Füge pro Seite <link rel="canonical"> in deine Metadaten ein |
| 6 | Saubere Heading-Hierarchie (H1 > H2 > H3) | Signalisiert Crawlern die Inhaltsstruktur | Eine H1 pro Seite, logische Verschachtelung in Komponenten |
| 7 | Interne Links nutzen echte <a href>-Tags | Nur JavaScript-Navigation (onClick-Handler) blockiert Crawler | Nutze Framework-Link-Komponenten: <Link>, <NuxtLink>, routerLink |
| 8 | XML-Sitemap eingereicht | Hilft Google, Seiten zu entdecken, die nicht über Links erreichbar sind | Generiere sie mit next-sitemap, nuxt-simple-sitemap oder Framework-spezifischen Tools |
| 9 | Code Splitting und Lazy Loading | Reduziert das initiale JS-Bundle, verbessert LCP und INP | Dynamische Imports (next/dynamic, defineAsyncComponent, @defer) |
| 10 | Schema Markup (JSON-LD) auf wichtigen Seiten | Ermöglicht Rich Snippets und hilft AI-Crawlern, Inhalte zu verstehen | JSON-LD in <head> oder <body> — serverseitig gerendert, nicht per JS injiziert |
Das sind die Fehler, die ich in fast jedem SPA-Audit sehe. Jeder einzelne davon zerstört Rankings.
„Aber Google rendert doch JavaScript!“ — ja, manchmal, irgendwann, wenn dein JS keinen Fehler wirft, wenn die Rendering-Warteschlange nicht überlastet ist, wenn dein JavaScript nicht ins Timeout läuft und wenn keine Third-Party-Skripte das Rendering stören. Das sind ziemlich viele Wenns, auf die du deinen organischen Traffic wetten würdest. Und AI-Crawler versuchen es nicht einmal.
// WRONG — CSR-only React app
// Google sees: <div id="root"></div>
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
// RIGHT — Next.js Server Component
// Google sees: fully rendered HTML with all content
export default async function Page() {
const data = await fetchData();
return <Article data={data} />;
}
Angulars HashLocationStrategy und der Hash-Modus von Vue Router erzeugen URLs wie example.com/#/products/shoes. Google ignoriert alles nach dem #. Deine komplette Anwendung sieht aus wie eine einzige Seite.
// WRONG — Vue Router hash mode
const router = createRouter({
history: createWebHashHistory(), // URLs: example.com/#/about
routes
})
// RIGHT — Vue Router history mode
const router = createRouter({
history: createWebHistory(), // URLs: example.com/about
routes
})
SPAs werden mit einem einzigen <title> in der HTML-Hülle ausgeliefert. Wenn du ihn nicht pro Route dynamisch aktualisierst, hat jede Seite denselben Title. Google indexiert dann eine Version und ignoriert den Rest.
<!-- WRONG — static HTML shell with one title -->
<!DOCTYPE html>
<html>
<head>
<title>My App</title> <!-- Same for every route -->
</head>
<body><div id="app"></div></body>
</html>
<!-- RIGHT — dynamic metadata per route (Nuxt example) -->
<script setup>
useHead({
title: `${product.name} | MyStore`,
meta: [{ name: 'description', content: product.summary }]
})
</script>
Ein einziger ungefangener Fehler in deiner Anwendung kann verhindern, dass die gesamte Seite gerendert wird. Googles Web Rendering Service versucht es nicht erneut. Die Seite bleibt leer im Index.
Ich sehe das ständig: Ein Third-Party-Analytics-Skript wirft einen Fehler, oder eine fehlende API-Response crasht den Component Tree. Das Ergebnis? Google indexiert eine leere Seite. Ein Kunde hatte ein Hotjar-Snippet, das im Renderer von Google gelegentlich fehlschlug. Ihre Produktseiten wurden im URL-Prüftool der GSC zufällig als leer angezeigt. Die Lösung war eine Error Boundary rund um die Analytics-Initialisierung. Hat 10 Minuten gedauert. Hat ihre Indexierung aber monatelang still beschädigt.
Fix: Füge Error Boundaries in React hinzu (ErrorBoundary-Komponenten), nutze NuxtErrorBoundary in Nuxt und teste immer mit deaktiviertem JavaScript (mehr dazu gleich).
SPAs mit clientseitigem Routing legen ihre URL-Struktur nicht über HTML-Links offen, wie klassische Multi-Page-Websites das tun. Ohne Sitemap entdeckt Google Seiten nur über crawlbare Links — und wenn dein internes Linking JavaScript-gesteuert ist, findet Google womöglich gar nichts.
# Install next-sitemap for Next.js
npm install next-sitemap
# next-sitemap.config.js
module.exports = {
siteUrl: 'https://example.com',
generateRobotsTxt: true,
changefreq: 'weekly',
// Exclude routes that shouldn't be indexed
exclude: ['/dashboard/*', '/api/*', '/admin/*'],
}
Wenn deine robots.txt CSS- oder JS-Dateien blockiert, kann Googles Renderer deine Seite nicht aufbauen. Das sehen wir überraschend oft — meistens als übrig gebliebene Standardkonfiguration.
# WRONG — blocking JS and CSS
User-agent: *
Disallow: /static/js/
Disallow: /static/css/
# RIGHT — allow all resources needed for rendering
User-agent: *
Disallow: /api/
Disallow: /dashboard/
Allow: /static/

Geh nicht davon aus, dass deine SPA crawlbar ist, nur weil sie in Chrome funktioniert. So prüfst du, was Suchmaschinen tatsächlich sehen.
Das URL-Prüftool ist dein bestes einzelnes Diagnosewerkzeug. Gib irgendeine URL ein und klicke auf „Live-URL testen“. Google ruft deine Seite ab, rendert sie mit seinem Web Rendering Service und zeigt dir das Ergebnis.
Worauf du achten solltest:
Das ist mein Lieblings-Test, weil er brutal ehrlich ist. Deaktiviere JavaScript in Chrome DevTools oder nutze eine Browser-Erweiterung und lade die Seite neu. Wenn du dann keinen Hauptinhalt, keine Navigation oder keine internen Links mehr siehst, hast du ein SEO-Problem. Nicht jede Seite muss ohne JavaScript perfekt interaktiv sein — aber die Inhalte, die ranken sollen, müssen sichtbar sein.
Ruf die URL direkt per curl ab und schau dir an, was in der ersten Serverantwort steckt. Wenn dort nur ein App-Grundgerüst und Script-Tags stehen, aber kein eigentlicher Seiteninhalt, lieferst du keine suchmaschinenfreundliche HTML-Antwort aus.
curl -A "Googlebot" -L https://example.com/product/widget-123
curl -A "GPTBot" -L https://example.com/product/widget-123
Vergleiche die Antworten. Im Idealfall sehen beide Bots denselben vollständigen HTML-Inhalt. Wenn GPTBot praktisch nichts außer einem Grundgerüst bekommt, weißt du sofort, warum du in AI-Suchergebnissen nicht auftauchst.
Unser kostenloses SEO-Audit-Tool scannt deine SPA auf Rendering-Probleme, fehlende Meta-Tags, defekte Links und Accessibility-Probleme. Es zeigt dir exakt, was Suchmaschinen sehen — kein Login nötig, Ergebnisse in 30 Sekunden.
Da AI-Crawler kein JavaScript rendern, solltest du mit dem AI Crawler Inspector prüfen, ob sie auf deinen Inhalt zugreifen können. Das Tool simuliert, wie GPTBot, ClaudeBot und andere AI-Bots deine Seiten sehen.
Die SPA-SEO-Landschaft sieht 2026 spürbar anders aus als noch vor zwei Jahren. Das ist es, worauf es jetzt ankommt.
Mit dem Next.js App Router werden Komponenten standardmäßig auf dem Server gerendert. Mit 'use client' entscheidest du dich explizit für clientseitiges Rendering. Das kehrt das alte Modell um — statt dass alles CSR ist und SSR irgendwie drangeschraubt wird, ist alles SSR und CSR wird nur dort ergänzt, wo es nötig ist. Die SEO-Auswirkungen sind erheblich: Der Großteil deiner Anwendung wird automatisch als pures HTML ausgeliefert.
Nuxt 3 mit Nitro, Next.js Edge Runtime und SvelteKit-Adapter deployen SSR inzwischen an CDN-Edge-Standorte (Cloudflare Workers, Vercel Edge Functions). Deine Seiten werden am Edge-Knoten gerendert, der dem Nutzer — oder Crawler — am nächsten ist. Sub-50ms TTFB sind global erreichbar.
Angular 17+ hat SSR mit ng new --ssr direkt in die CLI integriert. Angular 19 hat Incremental Hydration ergänzt. Die Zeiten schmerzhafter Angular-Universal-Setups sind vorbei. Wenn du immer noch eine reine CSR-Angular-App betreibst, ist der Migrationspfad heute ziemlich geradlinig.
GPTBot, ClaudeBot, PerplexityBot und andere crawlen das Web, um Trainingsdaten aufzubauen und AI-Suche zu betreiben. Keiner von ihnen führt JavaScript aus. Die Analyse von über einer halben Milliarde GPTBot-Requests fand keinerlei Hinweise auf JS-Ausführung. Wenn du willst, dass dein Inhalt in AI-generierten Antworten zitiert wird, ist SSR die einzige Option.
"Gerendertes HTML zu sehen und nicht nur den Source Code ist wichtig, um zu diagnostizieren, ob es ein Indexierungsproblem gibt. Google kann deine Links nur entdecken, wenn sie
<a>-HTML-Elemente mit einemhref-Attribut sind."
LCP, INP und CLS bleiben Ranking-Signale. SPAs mit großen JavaScript-Bundles werden bei LCP (die Seite braucht zu lange, um sinnvollen Inhalt anzuzeigen) und INP (Interaktionen fühlen sich träge an) abgestraft. Code Splitting, Lazy Loading und minimales clientseitiges JavaScript sind nicht optional — sie sind Performance-Anforderungen mit direktem Einfluss auf Rankings.
"Deine Website statisch oder auf dem Server vorzugenerieren ist die Best Practice für SEO — es macht Crawler eher bereit, deine Website häufiger neu zu indexieren."
Nicht sicher, welches Framework du wählen sollst? So schneiden sie speziell in Sachen SEO ab.
| Feature | Next.js (React) | Nuxt 3 (Vue) | Angular SSR | SvelteKit |
|---|---|---|---|---|
| SSR standardmäßig | Ja (App Router) | Ja | Ja (seit v17) | Ja |
| Statische Generierung | generateStaticParams | prerender: true | ng build --prerender | export const prerender = true |
| ISR-Unterstützung | Integriert (revalidate) | Integriert (isr: seconds) | Manuell über Service Worker | Über adapter-spezifische Konfiguration |
| Edge Rendering | Vercel Edge, Cloudflare | Nitro (plattformübergreifend) | Begrenzt | Mehrere Adapter |
| Metadata-API pro Seite | generateMetadata | useHead() | Meta- + Title-Services | <svelte:head> |
| Ausgeliefertes Client-JS | Mittel (RSC hilft) | Mittel | Schwer | Minimal (wegkompiliert) |
| Community/Ökosystem | Am größten | Stark | Enterprise-fokussiert | Wächst schnell |
Ja, aber mit Einschränkungen. Googles Web Rendering Service nutzt einen Headless-Chromium-Browser, um JavaScript auszuführen und SPAs zu rendern. Dieses Rendering passiert jedoch in einer separaten Rendering-Warteschlange nach dem ersten Crawling, was die Indexierung um Stunden bis Tage verzögern kann. Seiten mit JavaScript-Fehlern werden möglicherweise nie gerendert. Für zuverlässige Indexierung solltest du SSR oder SSG verwenden — verlass dich bei zeitkritischen Inhalten nicht auf Googles Rendering-Warteschlange.
Eine reine CSR-SPA ist schlecht für SEO. Eine SPA mit serverseitigem Rendering ist es nicht. Das Framework ist nicht entscheidend — entscheidend ist, ob die erste HTML-Antwort deinen Inhalt enthält. Next.js, Nuxt, Angular SSR und SvelteKit erzeugen alle vollständig crawlbare SPAs. Das „SPA vs. SEO“-Problem wurde vor Jahren gelöst; das eigentliche Problem sind Entwickler, die die Lösung nicht umsetzen.
Für jede Seite, die in der Suche ranken soll? Ja. React allein (über Vite oder Create React App) ist nur CSR — Suchmaschinen sehen eine leere Seite. Next.js ergänzt SSR, SSG und ISR. Mit React Server Components im App Router werden die meisten Komponenten standardmäßig auf dem Server gerendert. Wenn deine React-App öffentliche Inhalte ausliefert, ist Next.js die Standardlösung.
Gar nicht. GPTBot (OpenAI), ClaudeBot (Anthropic), PerplexityBot und andere AI-Crawler führen kein JavaScript aus. Sie parsen nur rohes HTML. Die Analyse von über einer halben Milliarde GPTBot-Requests fand keinerlei Hinweise auf JavaScript-Rendering. Wenn dein Inhalt clientseitig gerendert wird, ist er für AI-Suchmaschinen unsichtbar. SSR ist der einzige Weg, in AI-generierten Antworten und Zitaten aufzutauchen.
SSR (Server-Side Rendering) erzeugt HTML bei jedem Request — ideal für dynamische Inhalte. SSG (Static Site Generation) erzeugt HTML beim Build — am schnellsten, aber bei Inhaltsänderungen sind Rebuilds nötig. ISR (Incremental Static Regeneration) erzeugt statische Seiten, die sich nach Zeitplan automatisch neu generieren — kombiniert SSG-Geschwindigkeit mit frischem Inhalt. Alle drei liefern Suchmaschinen beim ersten Request vollständiges HTML. Die Wahl hängt davon ab, wie oft sich dein Inhalt ändert.
SPAs sind nicht grundsätzlich schlecht für SEO. Aber reine CSR-SPAs sind es — und 2026 sind sie auch für AI-Suchmaschinen unsichtbar.
Die Lösung gibt es seit Jahren. Next.js, Nuxt 3, Angular SSR und SvelteKit liefern serverseitig gerendertes HTML direkt mit. React Server Components haben den Standard sogar noch verbessert — der Großteil deiner App wird automatisch auf dem Server gerendert. Es gibt keinen guten Grund mehr, eine öffentliche SPA ohne serverseitiges Rendering auszuliefern.
Wenn du unsicher bist, ob deine SPA crawlbar ist, starte ein kostenloses Audit — es dauert 30 Sekunden und zeigt dir exakt, was Google sieht. Für die Sichtbarkeit bei AI-Crawlern prüfe den AI Crawler Inspector.
Passende weiterführende Artikel:
no credit card required