Angular-SEO
Wie Sie Angular-Anwendungen crawlbar und indexierbar machen: SSR, Prerendering, Hybrid-Rendering, Hydration, saubere URLs, Meta-Tags und Tests mit Googlebot.
Sprachen
Angular rendert standardmäßig clientseitig: Beim ersten Abruf sehen Crawler meist nur eine leere HTML-Hülle, während JavaScript die Seite später im Browser aufbaut. Verwenden Sie @angular/ssr für serverseitiges Rendering oder Prerendering für statische Routen; wählen Sie den Modus pro Route mit RenderMode. Hydratisieren Sie das Server-HTML, statt es neu zu rendern, setzen Sie eindeutige Titel und Beschreibungen über Title und Meta, verwenden Sie HTML5-History-Routing mit echten a-Links und prüfen Sie das Ergebnis mit URL Inspection. Dynamisches Rendering ist eine Übergangslösung, keine dauerhafte Strategie.
TL;DR — Angular baut die Seite standardmäßig mit JavaScript im Browser auf, deshalb ist das rohe HTML, das eine Suchmaschine zuerst sieht, fast leer. Die Lösung besteht darin, stattdessen echtes, fertiges HTML auszuliefern — mit Angulars integriertem serverseitigem Rendering (
@angular/ssr) oder Prerendering. Kümmern Sie sich anschließend um die Grundlagen: ein eindeutiger Titel und eine eindeutige Beschreibung auf jeder Seite, saubere URLs (ohne#) und echte<a href>-Links.
Das Problem in einem Satz
Eine Angular-Standardanwendung sendet dem Browser eine winzige HTML-Hülle — im Wesentlichen ein leeres <div> — und dazu ein großes JavaScript-Bundle. Ihr Browser führt dieses JavaScript aus, danach füllt sich die Seite mit Inhalt. Das nennt man clientseitiges Rendering (CSR).
Das Problem: Wenn eine Suchmaschine diese URL zum ersten Mal herunterlädt, sieht sie die leere Hülle. Google kann das JavaScript ausführen und den echten Inhalt sehen, tut das aber später, in einem separaten Schritt und nicht immer zuverlässig. Evidence for this claim Google can render JavaScript but processes rendering as a stage after crawling. Scope: Google Search rendering; other crawler behavior is not covered by this record. Confidence: high · Verified: Google: JavaScript SEO basics Andere Crawler — Bing und die Bots hinter Social-Previews — können JavaScript oft überhaupt nicht ausführen. Sie sehen daher nichts.
Die Lösung: fertiges HTML senden
Statt den Browser (oder Crawler) die Seite aufbauen zu lassen, bauen Sie die Seite vorab oder auf einem Server auf und senden das vollständige HTML. Angular bietet dafür zwei Hauptwege:
- Serverseitiges Rendering (SSR) — ein Server führt Angular für jede Anfrage aus und sendet die vollständige Seite zurück. Gut für Inhalte, die sich häufig ändern. Evidence for this claim Angular supports server-side rendering and build-time prerendering through its SSR tooling. Scope: Current Angular SSR and prerender features. Confidence: high · Verified: Angular: Server-side and hybrid rendering
- Prerendering — Angular erstellt beim Build statische HTML-Dateien für Ihre Seiten, sodass kein Server benötigt wird. Die schnellste Option und ideal für Blogbeiträge und Marketingseiten.
Modernes Angular (Version 17 und höher) bringt beides direkt im Toolkit mit. Sie fügen es mit einem Befehl hinzu: ng add @angular/ssr. (Vielleicht kennen Sie den alten Namen Angular Universal — es war dieselbe Idee als separates Add-on. Angular nahm es in v17 in den Kern auf und benannte es um.)
Die übrigen Grundlagen
- Geben Sie jeder Seite einen eindeutigen Titel und eine eindeutige Beschreibung. Angular erledigt das nicht für Sie — Sie setzen beides im Code mit Angulars integrierten Diensten
TitleundMeta. Andernfalls haben alle Seiten denselben Titel. - Verwenden Sie saubere URLs, keine Hash-URLs. Angulares Standard-Routing erzeugt schöne URLs wie
/products/shoes. Vermeiden Sie den älteren „Hash“-Stil (/#/products) — Suchmaschinen können den Teil nach dem#nicht zuverlässig verarbeiten. - Verwenden Sie echte Links. Die Navigation muss aus echten
<a href>-Links bestehen, nicht aus Buttons oder Click-Handlern, sonst kann Google ihnen nicht folgen.
Der häufigste Denkfehler
„Google kann Angular nicht indexieren“ ist ein Mythos — Google kann JavaScript rendern. Es ist aber langsamer und weniger zuverlässig, als echtes HTML zu senden, und Nicht-Google-Crawler können es überhaupt nicht. Für alles, was gefunden werden soll, rendern Sie daher auf dem Server oder prerendern es vor.
Möchten Sie die ausführliche Version — hybrides Rendering pro Route, Hydration, die SEO-Dienste mit Code und Tests dessen, was Google tatsächlich sieht? Wechseln Sie zum Tab Fortgeschritten.
Evidence for this claim Modern Angular documents @angular/ssr as its server-side and hybrid rendering package. Scope: Current Angular documentation; historical Angular Universal details are not required for this claim. Confidence: high · Verified: Angular: Server-side and hybrid renderingTL;DR — Angular-SEO ist eine Architekturentscheidung mit vielen Auswirkungen: Bringen Sie echtes HTML in die Antwort, statt eine clientseitig gerenderte Hülle zu senden. Modernes Angular (v17+) integriert SSR als
@angular/ssrin die CLI (der umbenannte, integrierte Nachfolger von Angular Universal). Prerendern Sie statische Routen, rendern Sie dynamische Routen auf dem Server und kombinieren Sie beides mit hybridem Rendering. Hydratisieren Sie anschließend, damit das Server-HTML wiederverwendet und nicht neu aufgebaut wird. Erledigen Sie dann die Grundlagen: eindeutige Titel und Beschreibungen über die DiensteTitle/Meta(oder dieTitleStrategydes Routers), HTML5-History-Routing — niemalsHashLocationStrategy—, echte<a href>-Links, sicher eingefügtes JSON-LD und die Prüfung über die URL Inspection. Dynamisches Rendering ist eine von Google anerkannte Übergangslösung, keine Strategie.
Das Standardproblem: clientseitiges Rendering
Ein Angular-Standardbuild liefert eine index.html, deren Body im Wesentlichen aus <app-root></app-root> und Script-Tags besteht. Ohne ausgeführtes JavaScript sieht ein Crawler keine Überschriften, keinen Text und keine Links — der Inhalt wird erst nach dem Laden des Bundles im Browser zusammengesetzt. Das ist dasselbe Kernproblem, das ich in JavaScript SEO beschreibe: Das Web hat sich von einfachem HTML wegbewegt, und CSR ist das riskanteste Ende dieses Spektrums.
(Die Implementierungsdetails dieses Leitfadens — RenderMode-APIs, Hydration-Trigger und Event-Replay — beziehen sich auf Angular v22. Versionsabhängige Funktionen sind datiert: die SSR-Umbenennung in v17, Event-Replay in v18 und inkrementelle Hydration in v19–v20.)
CSR erzeugt drei unterschiedliche SEO-Probleme:
- Verzögerte, weniger zuverlässige Indexierung. Google verarbeitet JS-Anwendungen in drei Phasen — “Crawling, Rendering, and Indexing” (Übersetzung) „Crawling, Rendering und Indexierung“ — und stellt das Rendering in eine Warteschlange zurück. Ihr Inhalt existiert für die Indexierung erst, wenn dieses Rendering ausgeführt wurde.
- Schlechtere Core Web Vitals. LCP leidet, weil der Browser ein Bundle herunterladen und ausführen muss, bevor er sinnvollen Inhalt zeichnet.
- Nicht-Google-Crawler sehen die Hülle. Bingbot rendert JavaScript deutlich weniger konsistent, und Social-/Link-Preview-Bots rendern im Allgemeinen überhaupt nicht — Open-Graph-Tags und clientseitig eingefügter Inhalt erreichen sie daher nie.
Wie Googlebot eine Angular-Anwendung tatsächlich verarbeitet
Googlebot ist evergreen — er rendert mit einer aktuellen Version von Chromes V8-Engine und wird zusammen mit Chrome aktualisiert. Evidence for this claim Googlebot uses an evergreen version of Chromium for rendering. Scope: Google Search rendering engine; this does not remove application-level rendering risks. Confidence: high · Verified: Google: Evergreen Googlebot Er kann Angular also ausführen. Das Verhalten hat jedoch harte Grenzen, um die herum Sie entwerfen sollten:
- Rendering wird eingereiht, nicht sofort ausgeführt. Google dokumentiert getrennte Phasen für Crawling, Rendering und Indexierung und veröffentlicht keinen festen Zeitplan dafür, wie lange das Rendering braucht, um zum Crawling aufzuschließen. Die Kurzform der Branche lautet „zwei Wellen“ — rohes HTML wird zuerst indexiert (bei CSR-Angular eine leere Hülle), das gerenderte DOM später, sobald das Rendering ausgeführt wird. SSR/Prerendering umgeht diese Wartezeit: Beim ersten Abruf ist das HTML vollständig, sodass für diesen Inhalt kein separater Rendering-Durchlauf abgewartet werden muss.
- Der Renderer ist zustandslos. Zwischen Ladevorgängen werden keine Cookies, kein
localStorageund keinsessionStorageübernommen; Berechtigungsdialoge werden abgelehnt. Machen Sie Inhalte nicht vom Client-Zustand abhängig. - Er klickt und scrollt nicht, und er rendert in einem sehr hohen Viewport. Inhalt hinter einer Interaktion wird nicht gesehen.
- Ressourcen werden aggressiv gecacht — verwenden Sie dateibasierte Fingerprints (Angulares Standard
main.<hash>.js), damit aktualisierte Bundles nicht veraltet ausgeliefert werden.
@angular/ssr — was es ist und die Geschichte der Benennung
Serverseitiges Rendering führt Angular pro Anfrage auf einem Node-Server aus und gibt vollständig gerendertes HTML zurück, das der Browser anschließend hydratisiert (Event-Listener an das bestehende DOM anfügt, statt erneut zu rendern). Jeder Crawler — Googlebot, Bingbot und Social-Bots — erhält beim ersten Abruf vollständiges HTML; eine zweite Welle ist nicht nötig.
Die Benennung sorgt für Verwirrung, daher die genaue Einordnung: „Angular Universal“ war die historische SSR-Lösung und wurde als externes Paket (@nguniversal/express-engine) ausgeliefert. Mit Angular v17 (November 2023) wurde SSR direkt in Angular CLI und Application Builder integriert und in @angular/ssr umbenannt; das Angular-Universal-Repository befindet sich inzwischen im Wartungsmodus. Evidence for this claim Modern Angular documents @angular/ssr as its server-side and hybrid rendering package. Scope: Current Angular documentation; historical Angular Universal details are not required for this claim. Confidence: high · Verified: Angular: Server-side and hybrid rendering Die Einrichtung ist jetzt ein Einzeiler:
# New project with SSR enabled
ng new my-app --ssr
# Add SSR to an existing project
ng add @angular/ssrDies ersetzt das alte ng add @nguniversal/express-engine. Dieselbe Idee, jetzt als erstklassiges Tooling.
Prerendering (statische Generierung / SSG)
Prerendering erzeugt statisches HTML für Routen zur Build-Zeit, sodass zur Anfragezeit kein Server läuft — Sie können die Anwendung auf einem CDN bereitstellen. Es bietet die schnellste TTFB/FCP/LCP und die niedrigsten Betriebskosten. In v17+ konfigurieren Sie es pro Route über eine Server-Routendatei (app.routes.server.ts) mit RenderMode.Prerender; outputMode: 'static' erzeugt eine vollständig statische Anwendung.
Die Einschränkung: Die Daten müssen zur Build-Zeit verfügbar sein, es darf keine nutzerspezifischen Inhalte geben, und sehr große Websites bedeuten langsame Builds. Das ist ideal für Marketingseiten, Dokumentation und Blogbeiträge — genau für Inhalte, die besonders ranken und zitiert werden sollen.
Hybrides Rendering — einen Modus pro Route wählen
Der große Fortschritt ab v17+ ist, dass der Rendering-Modus eine Entscheidung pro Route ist, konfiguriert in app.routes.server.ts:
RenderMode.Prerender— statische Routen (Startseite, Über-uns, Blogbeiträge).RenderMode.Server— dynamische Routen pro Anfrage (Suchergebnisse, Dashboards mit aktuellen Daten).RenderMode.Client— interne Routen, die Sie ohnehin nicht indexieren lassen möchten (Admin-Oberflächen, nur authentifizierte Ansichten). CSR ist hier tatsächlich in Ordnung.
Das ist die praktische Entscheidungsregel: Prerendern Sie, was statisch ist, rendern Sie auf dem Server, was aktuell sein muss, und fallen Sie nur für Dinge auf clientseitiges Rendering zurück, die nicht in den Index gehören.
Hydration — und der Fehler, der CLS ruiniert
Naives SSR hat einen Fehler: Der Server sendet HTML, dann verwirft der Browser es und rendert von Grund auf neu, was ein Aufblitzen und unnötige Arbeit verursacht. Hydration behebt das — der Browser stellt die serverseitig gerenderte Anwendung wieder her und verwendet das passende DOM erneut, statt es zu zerstören und neu zu erstellen; er bindet nur die Interaktivität an. Aktivieren Sie die Funktion in app.config.ts:
provideClientHydration()Voraussetzung: Hydration ist eine clientseitige Ergänzung zu SSR, kein eigenständiger Schalter. provideClientHydration() bewirkt nur auf einer Route etwas, die bereits serverseitig gerendert (oder prerendert) wird — die Hülle einer RenderMode.Client-Route kann dadurch nicht zu Server-HTML werden. Aktivieren Sie SSR/Prerendering zuerst für die Route.
Zwei neuere Fähigkeiten sind für SEO-nahe UX relevant — keine von ihnen verändert die Suchindexierung:
- Event-Replay (v18+): Erfasst unterstützte Nutzerinteraktionen, die vor Abschluss der Hydration stattfinden, und spielt sie danach erneut ab. Das reduziert verlorene Klicks für die unterstützten Interaktionstypen; es ist eine UX-/Interaktivitätsfunktion, keine SEO-Funktion, und hat keinen Einfluss darauf, was Google indexiert.
- Inkrementelle Hydration (Entwicklervorschau in v19, stabil in v20): Sie hängt gemeinsam von SSR, Hydration, aufschiebbaren Views und Event-Replay ab — sie ist keine eigenständige Funktion. Sie wird durch
@defer-Blöcke mit Hydration-Triggern gesteuert, die festlegen, welche Grenzen beim ersten Rendern dehydriert bleiben. Eine Grenze mithydrate neverbleibt beim ersten Laden dehydriert, ist aber nicht zwingend daran gehindert, ihre Abhängigkeiten bei späteren clientseitigen Renderings (z. B. nach einem Routenwechsel) zu laden. Die SEO-relevante Wirkung ist indirekt: Weniger anfänglich hydratisiertes JavaScript kann LCP verbessern, aber die Trigger-Konfiguration ist ein Rendering-Detail und kein Mechanismus für das Timing von Crawlern.
Der kritische Fehler: Wenn Sie @if (isPlatformBrowser(...)) direkt in einer Vorlage verwenden, rendern Server und Client unterschiedliches Markup — ein Hydration-Mismatch, der Layout-Verschiebungen verursacht und CLS verschlechtert. Verwenden Sie für reine Browserarbeit afterNextRender(), statt die Vorlage nach der Plattform zu verzweigen.
Titel und Meta-Tags — Angulares integrierte Dienste
Angular kann den Text des <title>-Elements nicht direkt binden; deshalb verwalten Sie Head-Tags über zwei Dienste aus @angular/platform-browser:
Title—setTitle()/getTitle().Meta—addTag(),addTags(),updateTag(),getTag(),removeTag(), mit Selektoren wiename='description'oderproperty='og:title'.
Für die Grundlagen benötigen Sie keine Bibliothek eines Drittanbieters. Ein gemeinsamer SEO-Dienst ist das saubere Muster:
@Injectable({ providedIn: 'root' })
export class SeoService {
private title = inject(Title);
private meta = inject(Meta);
updatePage(title: string, description: string) {
this.title.setTitle(title);
this.meta.updateTag({ name: 'description', content: description });
this.meta.updateTag({ property: 'og:title', content: title });
}
}Speziell für Titel können Sie mit der TitleStrategy des Routers (Angular v14+) einen title direkt in der Routenkonfiguration setzen, sodass sich der Seitentitel bei der Navigation automatisch aktualisiert — ohne Code pro Komponente. Setzen Sie document.title = ... nicht von Hand; verwenden Sie den Title-Dienst, damit es unter SSR korrekt funktioniert.
URL-Struktur
- Verwenden Sie das standardmäßige Routing über die HTML5 History API (
PathLocationStrategy) — saubere URLs wie/products/shoes. Dafür brauchtindex.html<base href="/">. - Verwenden Sie für öffentliche Inhalte niemals
HashLocationStrategy/useHash: true. Fragment-Identifier nach#werden vor der HTTP-Anfrage entfernt. Der Server sieht sie daher nie und Googlebot kann#/productsnicht zuverlässig auflösen — Ihre gesamte Website kann auf eine URL zusammenfallen. - Verwenden Sie echte
<a href>-Links für die Navigation, auch zu lazy geladenen Routen. Lazy Loading ist für die Performance in Ordnung, aber die Links zu diesen Routen müssen weiterhin crawlbare Anchor sein, keine Click-Handler.
Strukturierte Daten (JSON-LD)
Google unterstützt das Einfügen von JSON-LD mit JavaScript. Das robuste Angular-Muster ist ein Dienst, der ein <script type="application/ld+json"> erstellt und an document.head anhängt, wobei das Angular-Injection-Token DOCUMENT verwendet wird, statt document global anzusprechen (was auf dem Server fehlschlägt). Halten Sie das gesamte Schema an einer Stelle — teilen Sie es nicht zwischen statischem HTML und gerendertem DOM auf — und validieren Sie es mit dem Rich Results Test sowie der URL Inspection.
Dynamisches Rendering — eine alte Übergangslösung, kein Plan
Dynamisches Rendering liefert Bots eine prerenderte Version (über Puppeteer, Rendertron oder prerender.io) und Nutzern die vollständige SPA. Google sagt ausdrücklich: “dynamic rendering is a workaround and not a long-term solution,” (Übersetzung) „Dynamisches Rendering ist eine Übergangslösung und keine langfristige Lösung“ und es gebe “better solutions than dynamic rendering” (Übersetzung) „bessere Lösungen als dynamisches Rendering“ — nämlich serverseitiges Rendering, statisches Rendering oder Hydration. Es ist nicht automatisch Cloaking, solange Sie im Wesentlichen denselben Inhalt ausliefern, fügt aber einen zusätzlichen Rendering-Server hinzu, riskiert Inhaltsabweichungen und tut nichts für die Core Web Vitals echter Nutzer. Greifen Sie bei einem neuen Angular-Build stattdessen zu @angular/ssr oder Prerendering.
Häufige Angular-SEO-Fehler
- Hash-Routing (
#-URLs) — die gesamte Website sieht wie eine URL aus. - Keine
Title-/Meta-Aufrufe — jede Seite teilt sich Titel und Beschreibung. - Kein SSR/Prerendering — Inhalt existiert erst nach dem verzögerten Rendering-Durchlauf.
.js/.cssinrobots.txtblockieren — Google kann nicht rendern und indexiert eine leere Hülle.200für eine Nicht-gefunden-Ansicht zurückgeben — ein Soft-404; geben Sie ein echtes404zurück oder setzen Sienoindex.document.title = ...statt desTitle-Dienstes.isPlatformBrowser()in der Vorlagen-@if— Hydration-Mismatch → CLS.window/localStorage/documentin Code verwenden, der auf dem Server läuft — SSR-Abstürze.- Schema zwischen rohem HTML und gerendertem DOM aufteilen.
- Lokal statt mit URL Inspection testen — auf Annahmen statt auf Googlebot vertrauen.
Angular für SEO testen
- URL Inspection (Search Console) ist die maßgebliche Quelle: Die Ansicht der gecrawlten Seite zeigt das gerenderte HTML — das DOM, nachdem Googlebot JavaScript ausgeführt hat und genau das, was indexiert wird — sowie JS-Konsolenmeldungen und blockierte Ressourcen. Führen Sie für ein Rendering auf Abruf den Live-Test aus.
- Rufen Sie die URL mit
curlab, um das rohe HTML vor JavaScript zu sehen — eine leere Hülle bedeutet CSR ohne SSR. - Der Rich Results Test validiert strukturierte Daten.
- Ahrefs Site Audit (JS-Rendering aktiviert) und Screaming Frog (JS-Modus) vergleichen rohes und gerendertes DOM in großem Maßstab.
- Lighthouse / PageSpeed Insights messen den Einfluss Ihrer Rendering-Wahl auf die Core Web Vitals.
Angular ist nicht schlecht für SEO — es ist nur anders. Bringen Sie echtes HTML in die Antwort, verwalten Sie Ihre Head-Tags, halten Sie URLs und Links crawlbar und lassen Sie Googles eigene Tools entscheiden, was gerendert wurde. Dieses Thema steht neben JavaScript SEO und den Rendering-Fragen zu Headless-CMS in diesem Cluster — die grundlegende Lehre ist bei allen gleich: Der Rendering-Modus entscheidet fast alles.
KI-Zusammenfassung
Die Kurzfassung der Advanced-Version:
- Der Angular-Standard ist clientseitiges Rendering (CSR) — eine fast leere HTML-Hülle. Das bedeutet verzögerte/unsichere Indexierung, schlechteres LCP und dass Nicht-Google-Crawler (Bing, Social) nichts sehen.
- Googlebot ist evergreen und rendert JS, aber das Rendering wird eingereiht (die „zwei Wellen“ — rohes HTML zuerst, gerendertes DOM später, ohne festen Zeitplan), ist zustandslos (keine Cookies/kein Speicher), klickt und scrollt nicht und speichert Ressourcen konsequent zwischen. SSR/Prerendering umgeht die Wartezeit — das HTML ist beim ersten Abruf vollständig, es gibt also keinen separaten Rendering-Durchlauf abzuwarten.
@angular/ssrist die moderne Lösung — SSR ist seit v17 in die Angular CLI integriert und ersetzt das extern gepflegte Paket Angular Universal (@nguniversal/express-engine). Einrichtung:ng new --ssroderng add @angular/ssr.- Prerendering (statisches HTML zur Build-Zeit) ist am schnellsten und auf einem CDN bereitstellbar — am besten für statische Marketing-, Blog- und Dokumentationsinhalte; es ist auf Daten zur Build-Zeit beschränkt.
- Hybrides Rendering setzt den Modus pro Route in
app.routes.server.ts:RenderMode.Prerender(statisch),RenderMode.Server(dynamisch),RenderMode.Client(nicht indexierte interne Seiten). - Hydration (
provideClientHydration()) verwendet Server-HTML auf einer bereits SSR-/prerenderten Route wieder — sie erzeugt kein Server-HTML für CSR. Event-Replay (v18+) erfasst unterstützte Interaktionen vor der Hydration und spielt sie danach ab; inkrementelle Hydration (Vorschau v19 / stabil v20) hängt gemeinsam von SSR + Hydration + aufschiebbaren Views + Event-Replay ab und verwendet Hydration-Trigger von@defer, um festzulegen, welche Grenzen beim ersten Laden dehydriert bleiben (hydrate neverblockiert spätere clientseitige Ladevorgänge nicht). Keine dieser Funktionen verändert die Suchindexierung. Vermeiden SieisPlatformBrowser()in einer Vorlagen-@if— das verursacht einen Hydration-Mismatch → CLS; verwenden SieafterNextRender(). - Verwenden Sie die integrierten Dienste
TitleundMeta(keine Drittanbieterbibliothek nötig); dieTitleStrategydes Routers (v14+) setzt Titel pro Route automatisch. - Verwenden Sie HTML5-History-Routing, niemals Hash-URLs (
#); die Navigation muss aus echten<a href>-Anchor bestehen. JSON-LD kann über das TokenDOCUMENTeingefügt werden. - Dynamisches Rendering ist eine Übergangslösung, keine Strategie — Google empfiehlt stattdessen SSR/statisches Rendering/Hydration.
- Testen Sie mit URL Inspection (gerendertes HTML),
curl(rohes HTML), Rich Results Test und einem JS-rendernden Crawler. AngularJS ≠ Angular — alte AngularJS-Ratschläge gelten nicht.
Offizielle Dokumentation
Primärquellen von Google und Angular.
- Die Grundlagen von JavaScript-SEO verstehen — die Phasen Crawling → Rendering → Indexierung, crawlbare
<a href>-Links, Warnungen zum Fragment-Routing, Soft-404s und per JS eingefügte strukturierte Daten. - Dynamisches Rendering (Übergangslösung) — warum es eine Übergangslösung ist, die Cloaking-Nuance sowie Alternativen mit SSR/statischem Rendering/Hydration.
- Rendering im Web (web.dev — Addy Osmani & Jason Miller) — kanonische Definitionen von SSR, CSR, statischem Rendering und Hydration sowie deren Performance-Abwägungen.
- URL Inspection Tool — wie Sie das gerenderte HTML sehen, das Google tatsächlich indexiert, einschließlich JS-Konsolenmeldungen.
Angular
- Angular — serverseitiges und hybrides Rendering (SSR) — der offizielle Leitfaden zu
@angular/ssr, Server-Routen undRenderMode. - Angular — Dienst
Title—setTitle()/getTitle(). - Angular — Dienst
Meta—addTag(),updateTag()und Selektoren. - Angular — Router-Referenz —
PathLocationStrategygegenüber Hash-Routing undTitleStrategy. - Angular v17 vorstellen (Angular-Team-Blog) — SSR wird zu einer erstklassigen CLI-Funktion.
- Angular Universal (Wartungsmodus) — das historische Paket, das nun durch
@angular/ssrersetzt wurde.
Zitate aus den Quellen
Aussagen von Google und aus meinen eigenen Texten. Jeder Link zu einer Suchmaschine führt per Deep Link direkt zur zitierten Passage auf der Quellseite.
Google — wie JavaScript-Anwendungen verarbeitet werden
- “Google processes JavaScript web apps in three main phases: 1. Crawling 2. Rendering 3. Indexing.” (Übersetzung) „Google verarbeitet JavaScript-Webanwendungen in drei Hauptphasen: 1. Crawling, 2. Rendering, 3. Indexierung.“ — Dokumentation von Google Search Central. Zum Zitat springen
- “Google can only discover your links if they are <a> HTML elements with an href attribute.” (Übersetzung) „Google kann Ihre Links nur entdecken, wenn sie HTML-Elemente <a> mit einem href-Attribut sind.“ — Dokumentation von Google Search Central. Zum Zitat springen
Google — dynamisches Rendering ist eine Übergangslösung
- “Dynamic rendering was a workaround and not a long-term solution for problems with JavaScript-generated content in search engines.” (Übersetzung) „Dynamisches Rendering war eine Übergangslösung und keine langfristige Lösung für Probleme mit JavaScript-generierten Inhalten in Suchmaschinen.“ — Dokumentation von Google Search Central. Zum Zitat springen
web.dev — SSR / statisches Rendering bevorzugen (Addy Osmani & Jason Miller)
- “Rendering an app on the server to send HTML, rather than JavaScript, to the client.” (Übersetzung) „Beim serverseitigen Rendering wird eine Anwendung als HTML statt als JavaScript an den Client gesendet.“ — die Definition von serverseitigem Rendering. Zum Zitat springen
Patrick Stox (meine eigene Arbeit — JavaScript-SEO: Ein umfassender Leitfaden)
- “JavaScript is not bad for SEO, and it’s not evil. It’s just different from what many SEOs are used to.” (Übersetzung) „JavaScript ist nicht schlecht für SEO und nicht böse. Es ist nur anders, als viele SEO-Fachleute es gewohnt sind.“
- “Any kind of SSR, static rendering, and prerendering setup is going to be fine for search engines.” (Übersetzung) „Jede Einrichtung mit SSR, statischem Rendering oder Prerendering ist für Suchmaschinen geeignet.“
Angular-SEO-Checkliste
Ein schneller Durchgang, um zu bestätigen, dass eine Angular-Anwendung crawlbar und indexierbar ist:
- Öffentliche Inhalte werden als echtes HTML über
@angular/ssr(SSR) oder Prerendering ausgeliefert, nicht als vollständiges CSR. - Der Rendering-Modus wird pro Route in
app.routes.server.tsgesetzt — statische Routen prerendern, dynamische auf dem Server rendern und nur nicht indexierte interne Seiten clientseitig rendern. - Hydration ist aktiviert (
provideClientHydration()), und keine Vorlage verwendetisPlatformBrowser()in@if(stattdessenafterNextRender()). - Jede Seite setzt einen eindeutigen Titel (über den
Title-Dienst oder dieTitleStrategydes Routers) und eine eindeutige Beschreibung (über denMeta-Dienst). - Open-Graph-/Twitter-Card-Tags werden für Social-Previews mit dem
Meta-Dienst gesetzt. - Das Routing verwendet die HTML5 History API (Standard) mit
<base href="/">— nichtHashLocationStrategy/useHash: true. - Jede Navigation verwendet echte
<a href>-Anchor, auch Links zu lazy geladenen Routen. -
robots.txtblockiert keine.js- oder.css-Ressourcen. - Clientseitige Nicht-gefunden-Ansichten geben ein echtes
404zurück oder tragennoindex(keine Soft-404s). - Kein Zugriff auf
window/localStorage/documentin Code, der auf dem Server läuft (verwenden Sie dasDOCUMENT-Token bzw. Plattform-Guards). - JSON-LD befindet sich an einer Stelle und besteht den Rich Results Test.
- Sie haben das gerenderte HTML in URL Inspection überprüft — nicht nur die lokale Entwicklungsumgebung.
Die mentalen Modelle
1. Bringen Sie echtes HTML in die Antwort. Fast jedes Angular-SEO-Problem läuft auf eine Frage hinaus: Erhält der Crawler beim ersten Abruf fertiges HTML oder eine Hülle, die er rendern muss? SSR und Prerendering beantworten das mit „ja“. CSR antwortet „irgendwann, vielleicht“. Beginnen Sie jedes Audit hier.
2. Die Entscheidungsregel für Rendering pro Route.
- Statische Inhalte (Startseite, Über-uns, Blog, Dokumentation) →
RenderMode.Prerender. - Dynamische, aktuelle Inhalte (Suche, Live-Daten) →
RenderMode.Server. - Interne/authentifizierte Seiten, die nicht indexiert werden sollen →
RenderMode.Clientist in Ordnung.
3. „Angular Universal“ und „@angular/ssr“ sind dieselbe Idee aus verschiedenen Epochen.
Universal war das externe Paket; v17 nahm SSR in die CLI auf und benannte es um. Bei modernem Angular benötigen Sie @angular/ssr — das Universal-Repository befindet sich im Wartungsmodus.
4. Hydratisieren, nicht neu rendern.
Naives SSR sendet HTML und verwirft es anschließend. provideClientHydration() verwendet es wieder — aber nur auf einer bereits SSR-/prerenderten Route; für eine CSR-Route erzeugt es kein Server-HTML. Event-Replay und inkrementelle Hydration (@defer) reduzieren anfängliches JavaScript. Verzweigen Sie eine Vorlage niemals über isPlatformBrowser() — dadurch entsteht ein Hydration-Mismatch und ein CLS-Problem.
5. Head-Tags sind Ihre Aufgabe, nicht die von Angular.
Hier gibt es kein Yoast. Setzen Sie Titel und Beschreibungen pro Seite bewusst mit den Diensten Title/Meta (oder TitleStrategy). „Alle Seiten teilen sich einen Titel“ ist der Standardfehler, kein Pech.
6. Für einen zustandslosen Bot auf sauberen URLs entwerfen.
History-API-Routing, echte <a href>-Links, keine Abhängigkeit von Cookies/Speicher und kein Inhalt hinter einem Klick. Lassen Sie anschließend URL Inspection — nicht Ihren Laptop — feststellen, was gerendert wurde.
Angular-SEO — Spickzettel
Rendering-Modi
| Modus | Wo HTML erstellt wird | SEO | Am besten für | Angular-Konfiguration |
|---|---|---|---|---|
| Prerender (SSG) | Zur Build-Zeit → statische Dateien | ✅ Am besten | Statische Marketing-/Blog-/Dokumentationsinhalte | RenderMode.Prerender |
| SSR | Server, pro Anfrage | ✅ Sehr gut | Dynamische, aktuelle Inhalte | RenderMode.Server / @angular/ssr |
| Client (CSR) | Im Browser | ⚠️ Riskant | Interne/authentifizierte Seiten (nicht indexiert) | RenderMode.Client |
| Dynamisches Rendering | Separater Bot-Server | Nur Übergangslösung | Legacy-Anwendungen, die nicht migrieren können | Puppeteer / Rendertron / prerender.io |
Einrichtungsbefehle
| Ziel | Befehl |
|---|---|
| Neues Projekt mit SSR | ng new my-app --ssr |
| SSR zu bestehendem Projekt hinzufügen | ng add @angular/ssr |
| Hydration aktivieren | provideClientHydration() in app.config.ts |
Schnellregeln für Head und Routing
- Titel/Beschreibungen: Angulares Dienste
Title+Meta(keine Drittanbieterbibliothek nötig). - Automatische Titel pro Route: die
TitleStrategydes Routers (v14+) über dietitle-Eigenschaft der Route. - Routing: HTML5 History API +
<base href="/">. NiemalsuseHash: true. - Links: echte
<a href>-Anchor — auch zu lazy geladenen Routen. - JSON-LD: über das
DOCUMENT-Token einfügen; an einer Stelle halten.
Benennung
- Angular Universal = altes externes Paket (
@nguniversal/express-engine), Wartungsmodus. @angular/ssr= dasselbe SSR, seit v17 in die CLI integriert.- AngularJS (v1.x) ≠ Angular (v2+) — unterschiedliche Frameworks; alte AngularJS-Ratschläge gelten nicht.
Stolpersteine
isPlatformBrowser()in der Vorlagen-@if→ Hydration-Mismatch → CLS. Verwenden SieafterNextRender().window/localStorage/documentauf dem Server → SSR-Absturz..js/.cssin robots.txt blockieren → Google kann die Seite nicht rendern.
Prüfen, ob eine Angular-Anwendung tatsächlich serverseitig gerendert wird
Der schnellste Weg, um festzustellen, ob eine URL CSR oder SSR/Prerendering verwendet, ist der Abruf des rohen HTML (bevor JavaScript läuft) und die Suche nach echtem Inhalt. Eine CSR-Angular-Anwendung liefert ein fast leeres <app-root>; eine SSR-/prerenderte Anwendung liefert fertiges Markup.
macOS / Linux
# Raw HTML as the server sends it — this is the "first fetch", pre-JS
curl -sL -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
https://example.com/page/ -o raw.html
# Is your real headline in the raw HTML? Empty result = CSR with no SSR
grep -o "Your headline text" raw.html
# A near-empty <app-root> is the tell-tale CSR signature
grep -o "<app-root></app-root>" raw.htmlWindows (PowerShell)
$ua = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
Invoke-WebRequest -Uri "https://example.com/page/" -UserAgent $ua -OutFile raw.html
Select-String -Path raw.html -Pattern "Your headline text"
Select-String -Path raw.html -Pattern "<app-root></app-root>"Wenn die Überschrift fehlt und Sie ein leeres <app-root> sehen, hängt der Inhalt vom Rendering ab — fügen Sie SSR oder Prerendering hinzu. (Für das gerenderte DOM verwenden Sie in URL Inspection „View Crawled Page → rendered HTML“; ein einfacher curl kann kein JavaScript ausführen.)
Bestätigen, dass Sie Angulares JS/CSS nicht in robots.txt blockieren
macOS / Linux
curl -sL https://example.com/robots.txt | grep -iE "disallow.*\.(js|css)|Disallow:\s*/(assets|dist|main)"Ein Disallow, das auf Ihr Bundle zutrifft, bedeutet, dass Google die Seite nicht korrekt rendern kann — fast immer ein Fehler.
Tools zum Debuggen von Angular-SEO
- URL Inspection (Google Search Console) — die maßgebliche Quelle. Führen Sie einen Live-Test aus und lesen Sie anschließend das gerenderte HTML (das DOM, nachdem Googlebot Ihr Angular-JS ausgeführt hat), den Screenshot, die Seitenressourcen (was geladen bzw. blockiert wurde) und JavaScript-Konsolenmeldungen.
- Rich Results Test — bestätigen, dass Ihr JSON-LD nach einer Rendering-Änderung in der gerenderten Ausgabe vorhanden ist.
curl— ruft das rohe HTML vor JavaScript ab und unterscheidet CSR (leeres<app-root>) von SSR/Prerendering.- Ahrefs Site Audit (JS-Rendering aktiviert) — crawlt mit Headless Chrome, vergleicht rohes und gerendertes DOM und zeigt fehlende Metadaten, fehlerhafte Canonicals und Indexierbarkeitsprobleme im großen Maßstab.
- Screaming Frog SEO Spider (JS-Rendering-Modus) — vergleicht rohes und gerendertes DOM pro URL.
- Lighthouse / PageSpeed Insights — misst den Einfluss Ihrer Rendering-Strategie (CSR gegenüber SSR/Prerendering) auf die Core Web Vitals.
- Angular CLI / DevTools — bestätigt, dass
outputMode, Server-Routen und Hydration wie erwartet konfiguriert sind.
Ressourcen, die Ihre Zeit wert sind
Meine verwandten Texte
- JavaScript-SEO: Ein umfassender Leitfaden — mein vollständiger Leitfaden zu Rendering, DOM-Parität, der restriktivsten Direktive und sicheren Rendering-Konfigurationen. Angular-SEO ist eine konkrete Anwendung all dessen.
- Leitfaden für Einsteiger in technisches SEO — dort wird eingeordnet, wie Rendering und Crawling in das größere Bild passen.
Meine Vorträge
- JavaScript SEO — Ungagged 2019 (SlideShare) — Googles zustandsloses Rendering, Viewport und Caching sowie die damaligen Rendering-Ansätze. (Der übliche Hinweis: Die Empfehlung zum dynamischen Rendering in diesem Vortrag ist inzwischen veraltet — Google nennt es mittlerweile eine Übergangslösung.)
Aus der Branche
- Rendering im Web (web.dev) — Addy Osmani und Jason Millers kanonischer Text zu SSR, CSR, statischem Rendering und den Abwägungen von Hydration.
- Serverseitiges und hybrides Rendering (SSR) (angular.dev) — der offizielle Leitfaden zu
@angular/ssr, Server-Routen,RenderMode, Prerendering und Hydration. - Angular v17 vorgestellt (Angular-Team-Blog) — die Veröffentlichung, die SSR zu einer erstklassigen CLI-Funktion machte und das Paket
@angular/ssreinführte. - Angular Universal (Wartungsmodus) (GitHub) — das historische SSR-Paket, das durch
@angular/ssrersetzt wurde; nützlich zum Verständnis der Umbenennung. - Angular-SEO-Leitfaden (Search Engine Journal, Jamie Indigo) — der klassische Leitfaden zur Indexierung in zwei Wellen; stark bei den Grundlagen, obwohl er vor der Umbenennung in v17 entstand.
- Leitfaden für Angular-SSR (Angular Architects, Alexander Thalhammer, März 2025) — ein code-lastiger Leitfaden zur SSR-Einrichtung; prüfen Sie die Codebeispiele wegen API-Änderungen seit der Veröffentlichung gegen die offiziellen
@angular/ssr-Dokumente. - r/TechSEO — die Community für das Debugging von Rendering und Indexierung.
Angular-SEO-Anti-Patterns
Konkrete Fehler, die ich in Angular-Anwendungen immer wieder sehe — jede dieser Gewohnheiten sollte direkt geprüft werden, nicht nur als theoretisches Risiko.
Einen reinen CSR-Build ausliefern und ihn als fertig betrachten
Die Standardausgabe von ng new enthält kein SSR und kein Prerendering. Das ist der schnellste Weg, ein Projekt zu starten, und der einfachste Weg, beim ersten Abruf bei einem leeren <app-root> zu landen. Warum das falsch ist: Das rohe HTML, das ein Crawler sieht, enthält keinen Inhalt; die Indexierung hängt vollständig von Googles verzögertem Rendering ab — und andere Bots bekommen überhaupt keine zweite Chance. Besser: Fügen Sie zu Beginn des Projekts @angular/ssr hinzu (ng new my-app --ssr) oder führen Sie bei einem bestehenden Projekt ng add @angular/ssr aus, bevor Sie etwas ausliefern, das gefunden werden soll.
HashLocationStrategy für öffentliche Routen verwenden
Hash-Routing (useHash: true, URLs wie /#/products/shoes) ist in älteren Angular-Tutorials und Boilerplates noch immer der Standard. Warum das falsch ist: Alles nach dem # wird clientseitig entfernt, bevor die Anfrage den Server erreicht; der Server — und Googlebot — sieht daher für die gesamte Anwendung nur eine URL. Besser: Verwenden Sie das standardmäßige Routing über die HTML5 History API (PathLocationStrategy) mit <base href="/"> in index.html.
Eine Vorlage auf isPlatformBrowser() verzweigen
Inhalte mit @if (isPlatformBrowser(platformId)) zu umschließen, wirkt wie der naheliegende Weg, browsergebundenen Code abzusichern. Warum das falsch ist: Der Server rendert einen Zweig und der Client beim Hydratisieren den anderen — ein Hydration-Konflikt. Angular muss die Differenz ausgleichen, und das sichtbare Ergebnis ist eine Layout-Verschiebung, die sich im CLS niederschlägt. Besser: Verwenden Sie für reine Browserarbeit afterNextRender(), damit die Vorlage auf Server und Client identisch gerendert wird.
document.title direkt statt des Title-Dienstes setzen
In der lokalen Entwicklung funktioniert das, daher ist es eine verlockende Abkürzung. Warum das falsch ist: Direkter DOM-Zugriff wie document.title = '...' funktioniert unter SSR nicht gut — auf dem Server gibt es kein globales document in derselben Form wie im Browser, und Sie verlieren die Vorteile der Router-Integration für die Titelverwaltung durch Angular. Besser: Injizieren Sie Angulares Title-Dienst (setTitle()) oder konfigurieren Sie Titel pro Route mit der TitleStrategy des Routers.
window, localStorage oder document in Code verwenden, der während SSR läuft
Eine Komponente oder ein Dienst, der beim Erzeugen localStorage liest oder window.innerWidth prüft, funktioniert im Browser und stürzt beim Server-Rendering ab. Warum das falsch ist: Keines dieser globalen Objekte existiert im Node-Serverprozess, der Ihren SSR-Build ausführt; das Rendering wirft daher einen Fehler, und die Anfrage liefert entweder 500s oder fällt unbemerkt auf eine leere Antwort zurück. Besser: Sichern Sie den Code mit afterNextRender() ab oder injizieren Sie Angulars DOCUMENT-Token statt des globalen Objekts, und testen Sie den SSR-Build lokal (ng build plus Auslieferung der SSR-Ausgabe), nicht nur mit ng serve.
Dynamisches Rendering als dauerhafte Lösung behandeln
Puppeteer oder einen Dienst wie Rendertron einzurichten, um Bots einen prerenderten Snapshot auszuliefern, behebt das unmittelbare Symptom. Warum das falsch ist: Es ist ein zusätzliches System, das gewartet werden muss, kann von der Ansicht echter Nutzer abweichen, und Google hat ausdrücklich gesagt, dass es eine Übergangslösung statt einer langfristigen Lösung ist. Besser: Migrieren Sie zu @angular/ssr oder Prerendering, damit jede anfragende Person — Bot oder Mensch — dasselbe echte HTML aus derselben Pipeline erhält.
Welchen Rendering-Modus sollte diese Route verwenden?
Mit Angular v17+ können Sie den Rendering-Modus pro Route in app.routes.server.ts festlegen. Die Frage lautet nicht „SSR oder Prerendering für die gesamte Anwendung?“, sondern: Was soll diese einzelne Route verwenden?
Choosing a rendering mode for an Angular route
Prompts für Angular-SEO-Arbeit
Bereit zum Kopieren: Prompts für die konkreten Angular-SEO-Aufgaben in diesem Artikel. Fügen Sie die beschriebene Eingabe ein und prüfen Sie die Ausgabe anhand Ihres eigenen Urteils — sie sparen Zeit bei mechanischen Teilen, ersetzen aber nicht die Prüfung mit URL Inspection.
1. Rohes und gerendertes HTML einer Route vergleichen
Fügen Sie die Ausgabe von curl -sL <url> (rohes HTML) und das Panel „rendered HTML“ eines URL-Inspection-Live-Tests (oder eines JS-Rendering-Crawls von Ahrefs/Screaming Frog) für dieselbe URL ein.
Here is the raw HTML for [URL] (fetched with curl, before JavaScript runs):
[paste raw HTML]
Here is the rendered HTML for the same URL (from Google Search Console URL
Inspection's Live Test, or a JS-rendering crawler):
[paste rendered HTML]
Compare the two. List: (1) content present in rendered but missing from raw —
this is what depends on client-side rendering, (2) any <title>, meta description,
or JSON-LD that differs between the two versions, (3) whether the raw HTML shows
a near-empty <app-root> (a sign of CSR with no SSR/prerendering).Erwarten Sie eine kurze Liste dessen, was von CSR abhängt, sowie aller Abweichungen bei Titel/Meta/Schema zwischen rohem und gerendertem HTML — die beiden Dinge, die zuerst behoben werden sollten.
2. Eine Title-/Meta-Dienstimplementierung prüfen
Fügen Sie Ihren Angular-SeoService (oder ein Äquivalent) ein, der die Dienste Title und Meta aufruft.
Here is an Angular service that sets page titles and meta tags:
[paste the service's TypeScript code]
Check it against these rules: (1) titles are set via the Title service's
setTitle(), never document.title directly, (2) description is set with
meta.updateTag({ name: 'description', ... }) not addTag() (which can duplicate
the tag on repeat calls), (3) Open Graph tags use the property selector, not
name, (4) nothing in this code reads window/localStorage/document directly in a
way that would break during SSR. Flag any line that violates one of these and
suggest the fix.Erwarten Sie einen zeilenweisen Pass/Fail gegen diese vier Regeln, mit einem korrigierten Ausschnitt für jede markierte Stelle.
3. app.routes.server.ts auf Fehler beim Rendering-Modus prüfen
Fügen Sie Ihre Konfigurationsdatei für Server-Routen ein.
Here is my Angular app.routes.server.ts, which sets RenderMode per route:
[paste the file]
For each route, tell me: is RenderMode.Prerender used on anything that depends
on per-request or per-user data (a mistake — it would bake stale/wrong data into
the static build)? Is RenderMode.Client used on anything that looks like public,
indexable content (a missed-SEO-opportunity)? Is RenderMode.Server used on fully
static content where Prerender would be faster and cheaper? List each route with
its current mode and whether it matches the decision rule: static data →
Prerender, must-be-fresh → Server, non-indexed internal → Client.Erwarten Sie ein Ergebnis pro Route, das jede Route markiert, deren RenderMode nicht zu dem passt, was sie tatsächlich benötigt.
Testen Sie sich selbst: Angular-SEO
Fünf schnelle Fragen dazu, wie Angular-Anwendungen crawlbar und indexierbar werden. Wählen Sie jeweils eine Antwort und prüfen Sie anschließend.
Änderungsprotokoll
Aktualisiert am 14. Aug. 2026.
Redaktionelle Zusammenfassung und aufgezeichnete Änderungsdetails.Änderungsdetails
-
Detaillierte Änderungsangaben sind derzeit auf Englisch verfügbar.
Vollständiger Vergleich nicht verfügbar — für diese Version wurde kein früherer Schnappschuss archiviert.
Aktualisiert am 8. Aug. 2026.
Redaktionelle Zusammenfassung und aufgezeichnete Änderungsdetails.Änderungsdetails
-
Detaillierte Änderungsangaben sind derzeit auf Englisch verfügbar.
-
Detaillierte Änderungsangaben sind derzeit auf Englisch verfügbar.
-
Detaillierte Änderungsangaben sind derzeit auf Englisch verfügbar.
Vollständiger Vergleich nicht verfügbar — für diese Version wurde kein früherer Schnappschuss archiviert.
Aktualisiert am 8. Aug. 2026.
Redaktionelle Zusammenfassung und aufgezeichnete Änderungsdetails.Änderungsdetails
-
Detaillierte Änderungsangaben sind derzeit auf Englisch verfügbar.
Vollständiger Vergleich nicht verfügbar — für diese Version wurde kein früherer Schnappschuss archiviert.
Aktualisiert am 17. Juli 2026.
Redaktionelle Zusammenfassung und aufgezeichnete Änderungsdetails.Änderungsdetails
-
Detaillierte Änderungsangaben sind derzeit auf Englisch verfügbar.
-
Detaillierte Änderungsangaben sind derzeit auf Englisch verfügbar.
-
Detaillierte Änderungsangaben sind derzeit auf Englisch verfügbar.
Vollständiger Vergleich nicht verfügbar — für diese Version wurde kein früherer Schnappschuss archiviert.