Panduan Angular SEO

cara membuat Angular apps dapat di-crawl dan dapat diindeks — @angular/ssr vs prerendering vs hybrid rendering, hydration, judul/Meta services, History API routing, dan testing apa Googlebot sebenarnya renders.

Pertama kali diterbitkan: 26 Jun 2026 · Terakhir diperbarui: 8 Agu 2026 · Advanced
Bahasa

Angular SEO adalah benar-benar satu decision: sajikan nyata HTML alih-alih sebuah client-dirender shell. Modern Angular (v17+) membangun SSR ke CLI sebagai @angular/ssr — prerender static routes, server-render dynamic ones, hydrate so HTML tidak thrown away. lalu melakukan basics: unique judul/deskripsi melalui Angular's judul dan Meta services, HTML5 History routing (tidak pernah hash URLs), nyata <a href> tautan, dan verify dengan pemeriksaan URL. Dynamic rendering adalah sebuah workaround, tidak sebuah strategy — dan AngularJS adalah sebuah berbeda kerangka kerja.

TL;DR — Angular SEO adalah satu architectural decision wearing sebuah lot dari hats: mendapatkan nyata HTML ke respons alih-alih sebuah client-dirender shell. Modern Angular (v17+) membangun SSR ke CLI sebagai @angular/ssr ( rebranded, integrated successor untuk Angular Universal). Prerender static routes, server-render dynamic ones, mix them dengan hybrid rendering, dan hydrate so server HTML adalah reused tidak rebuilt. lalu melakukan blocking-dan-tackling: unique judul/deskripsi melalui Title/Meta services (atau router’s TitleStrategy), HTML5 History routing — tidak pernah HashLocationStrategy — nyata <a href> tautan, JSON-LD injected safely, dan verification melalui URL Inspection. Dynamic rendering adalah sebuah Google-acknowledged workaround, tidak sebuah strategy.

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

default adalah masalah: rendering sisi klien

sebuah stock Angular bangun ships sebuah index.html milik siapa body adalah essentially <app-root></app-root> plus script tags. Tanpa executing JavaScript, sebuah crawler sees Tidak heading, Tidak copy, Tidak tautan — konten adalah assembled di browser setelah bundle memuat. ini adalah yang sama core issue I deskripsikan di JavaScript SEO: web moved off plain HTML, dan CSR adalah riskiest end dari itu spectrum.

(ini guide’s implementation detail — RenderMode APIs, hydrate triggers, event replay — reflect Angular v22. versi-spesifik fitur di bawah adalah dated: v17 SSR rename, v18 event replay, v19–v20 incremental hydration.)

CSR membuat three distinct SEO masalah:

  1. Delayed, lebih sedikit-reliable pengindeksan. Google memproses JS apps di three phases — “Crawling, Rendering, dan Indexing” (terjemahan) “crawling, rendering, dan pengindeksan” — dan rendering adalah deferred ke sebuah queue. Anda konten tidak exist untuk pengindeksan until itu render berjalan.
  2. Worse Core Web Vitals. LCP suffers karena browser harus download dan execute sebuah bundle sebelum painting bermakna konten.
  3. Non-Google crawler see shell. Bingbot adalah far lebih sedikit consistent di JS rendering, dan social/tautan-preview bot umumnya jangan render di semua — so Open Graph tags dan konten injected client-side tidak pernah reach them.

Bagaimana Googlebot sebenarnya menangani sebuah Angular app

Googlebot adalah evergreen — ini renders dengan sebuah saat ini versi dari Chrome’s V8 mesin dan memperbarui alongside Chrome releases. 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 So ini dapat jalankan Angular. tetapi perilaku memiliki hard edges worth designing sekitar:

  • rendering adalah queued, tidak immediate. Google documents distinct crawling, rendering, dan pengindeksan phases dan tidak publish sebuah fixed timetable untuk bagaimana panjang rendering langkah takes untuk catch up untuk crawling. industry shorthand untuk ini adalah “dua waves” (terjemahan) “dua waves” — mentah HTML terindeks pertama (sebuah blank shell untuk CSR Angular), dirender DOM terindeks kemudian, setiap kali itu render berjalan. SSR/prerendering sidesteps tunggu: HTML adalah menyelesaikan pada pertama fetch, so ada Tidak terpisah render lulus untuk itu konten untuk tunggu pada.
  • ** renderer adalah stateless.** Tidak cookies, Tidak localStorage, Tidak sessionStorage carried antara memuat; ini declines permission prompts. jangan gate konten pada client state.
  • ini tidak click atau scroll, dan ini renders di sebuah very tall viewport. konten behind sebuah interaction tidak akan menjadi seen.
  • Resources adalah cached aggressively — gunakan konten-fingerprinted filenames (Angular’s default main.<hash>.js) so diperbarui bundles tidak disajikan stale.

@angular/ssr — apa ini adalah dan naming history

rendering sisi server berjalan Angular pada sebuah Node server per permintaan dan mengembalikan fully dirender HTML, yang browser lalu hydrates (attaches event listeners untuk existing DOM alih-alih re-rendering). setiap crawler — Googlebot, Bingbot, social bot — mendapatkan menyelesaikan HTML pada pertama permintaan, Tidak kedua wave diperlukan.

naming trips orang up, so menjadi precise: “Angular Universal” (terjemahan) “Angular Universal” adalah historical SSR solusi, shipped sebagai sebuah external package (@nguniversal/express-engine). dengan Angular v17 (November 2023), SSR adalah integrated secara langsung ke Angular CLI dan Application Builder dan renamed @angular/ssr; Angular Universal repository adalah now di maintenance mode. 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 setup adalah now sebuah satu-liner:

# New project with SSR enabled
ng new my-app --ssr

# Add SSR to an existing project
ng add @angular/ssr

ini replaces old ng add @nguniversal/express-engine. sama idea, pertama-class tooling.

Prerendering (static generation / SSG)

Prerendering generates static HTML untuk routes di bangun time, so Tidak server berjalan di permintaan time — Anda dapat deploy untuk sebuah CDN. ini memberikan fastest TTFB/FCP/LCP dan lowest operational cost. di v17+ Anda configure ini per route melalui sebuah server routes file (app.routes.server.ts) menggunakan RenderMode.Prerender, dan outputMode: 'static' produces sebuah fully static app.

constraint: data harus menjadi tersedia di bangun time, ada Tidak per-pengguna konten, dan very besar situs berarti slow membangun. ini adalah ideal untuk marketing halaman, docs, dan blog posts — persis konten itu sebagian besar perlu untuk peringkat dan menjadi cited.

Hybrid rendering — choose sebuah mode per route

big v17+ advancement adalah itu rendering mode adalah sebuah per-route decision, configured di app.routes.server.ts:

  • RenderMode.Prerender — static routes (home, tentang, blog posts).
  • RenderMode.Server — dynamic, per-permintaan routes (hasil pencarian, dashboards dengan fresh data).
  • RenderMode.Client — internal-hanya routes Anda tidak ingin terindeks anyway (admin UIs, authenticated-hanya screens). CSR adalah genuinely fine di sini.

ini adalah decision aturan dalam praktik: prerender apa static, server-render apa harus menjadi fresh, dan hanya fall back untuk client rendering untuk hal itu tidak seharusnya menjadi di indeks.

Hydration — dan pitfall itu wrecks CLS

Naive SSR memiliki sebuah flaw: server mengirim HTML, lalu browser throws ini away dan re-renders dari scratch, causing sebuah flash dan wasted berfungsi. Hydration memperbaiki itu — browser restores server-dirender app dan reuses matching DOM alih-alih destroying dan recreating ini, hanya wiring up interactivity. Enable ini di app.config.ts:

provideClientHydration()

Prerequisite: hydration adalah sebuah client-side companion untuk SSR, tidak sebuah standalone switch. provideClientHydration() hanya melakukan sesuatu pada sebuah route itu’s sudah server-dirender (atau prerendered) — ini dapat’t turn sebuah RenderMode.Client route’s shell ke server HTML. Enable SSR/prerendering untuk route pertama.

Dua newer capabilities penting untuk SEO-berdekatan UX — neither perubahan Penelusuran pengindeksan:

  • Event replay (v18+): captures didukung pengguna interactions itu happen sebelum hydration finishes dan replays them setelah ini menyelesaikan. ini reduces lost clicks untuk interaction jenis ini mendukung; ini adalah sebuah UX/interactivity fitur, tidak sebuah SEO satu, dan ini memiliki Tidak effect pada apa Google indeks.
  • Incremental hydration (v19 developer preview, stable di v20): bergantung pada SSR, hydration, deferrable views, dan event replay together — ini tidak sebuah standalone fitur. ini adalah powered oleh @defer blocks dengan hydrate triggers itu control yang boundaries stay dehydrated pada awal render; sebuah hydrate never boundary tetap dehydrated pada pertama muat tetapi tidak niscaya blocked dari memuat -nya dependencies pada kemudian client-side renders (e.g., setelah sebuah route perubahan). SEO-relevant effect adalah indirect: lebih sedikit JavaScript hydrated upfront dapat help LCP, tetapi trigger config adalah sebuah rendering detail, tidak sebuah crawler-timing mechanism.

** critical pitfall:** putting @if (isPlatformBrowser(...)) secara langsung di sebuah template penyebab server dan client untuk render berbeda markup — sebuah hydration mismatch — yang produces layout shift dan damages CLS. gunakan afterNextRender() untuk browser-hanya berfungsi alih-alih branching template pada platform.

judul dan meta tags — Angular’s dibangun-di services

Angular dapat’t bind secara langsung untuk <title> element’s text, so Anda manage head tags melalui dua services dari @angular/platform-browser:

  • TitlesetTitle() / getTitle().
  • MetaaddTag(), addTags(), updateTag(), getTag(), removeTag(), dengan selectors like name='description' atau property='og:title'.

Anda melakukan tidak perlu sebuah ketiga-party library untuk basics. sebuah shared SEO service adalah bersih pattern:

@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 });
  }
}

untuk judul secara khusus, router’s TitleStrategy (Angular v14+) lets Anda set sebuah title secara langsung di route config so halaman judul memperbarui secara otomatis pada navigation — Tidak per-component code. dan jangan set document.title = ... oleh hand; gunakan Title service so ini berfungsi correctly di bawah SSR.

struktur URL

  • gunakan default HTML5 History API routing (PathLocationStrategy) — bersih URLs like /products/shoes. ini perlu <base href="/"> di index.html.
  • tidak pernah gunakan HashLocationStrategy / useHash: true untuk publik konten. Fragment identifiers setelah # adalah stripped sebelum HTTP permintaan, so server tidak pernah sees them dan Googlebot dapat’t reliably resolve #/products — Anda seluruh situs dapat collapse untuk satu URL.
  • nyata <a href> tautan untuk navigation, including untuk lazy-dimuat routes. Lazy memuat adalah fine untuk performa, tetapi tautan untuk itu routes masih memiliki untuk menjadi dapat di-crawl anchors, tidak click handlers.

data terstruktur (JSON-LD)

Google mendukung injecting JSON-LD dengan JavaScript. robust Angular pattern adalah sebuah service itu membuat sebuah <script type="application/ld+json"> dan appends ini untuk document.head, menggunakan Angular’s DOCUMENT injection token alih-alih touching document globally (yang breaks pada server). pertahankan semua schema di satu place — jangan split ini antara static HTML dan dirender DOM — dan validate dengan Rich hasil Test plus pemeriksaan URL.

Dynamic rendering — sebuah legacy workaround, tidak sebuah plan

Dynamic rendering menyajikan sebuah prerendered versi untuk bot (melalui Puppeteer, Rendertron, atau prerender.io) dan penuh SPA untuk pengguna. Google adalah jelas itu “dynamic rendering is a workaround and not a long-term solution,” (terjemahan) “dynamic rendering adalah workaround dan bukan solusi jangka panjang,” dan itu ada “better solutions than dynamic rendering” (terjemahan) “solusi yang lebih baik daripada dynamic rendering” — namely rendering sisi server, static rendering, atau hydration. ini adalah tidak secara otomatis cloaking sebagai panjang sebagai Anda sajikan substantially similar konten, tetapi ini menambahkan sebuah extra rendering server, risks konten drift, dan melakukan tidak ada apa pun untuk pengguna nyata’ Core Web Vitals. untuk sebuah baru Angular bangun, reach untuk @angular/ssr atau prerendering alih-alih.

umum Angular SEO mistakes

  1. Hash routing (# URLs) — seluruh situs looks like satu URL.
  2. Tidak Title/Meta panggilan — setiap halaman shares satu judul dan deskripsi.
  3. Tidak SSR/prerendering — konten hanya ada setelah deferred render wave.
  4. Blocking .js/.css di robots.txt — Google dapat’t render, indeks sebuah empty shell.
  5. Returning 200 pada sebuah tidak-ditemukan view — sebuah soft 404; mengembalikan nyata 404 atau tambahkan noindex.
  6. document.title = ... alih-alih Title service.
  7. isPlatformBrowser() di dalam template @if — hydration mismatch → CLS.
  8. Touching window/localStorage/document di code itu berjalan pada server — SSR crashes.
  9. Splitting schema antara mentah HTML dan dirender DOM.
  10. Testing di local dev alih-alih dengan pemeriksaan URL — relying pada assumptions, tidak Googlebot.

Testing Angular untuk SEO

  • pemeriksaan URL (Search Console) adalah sumber kebenaran: di-crawl-halaman view menampilkan dirender HTML — DOM setelah Googlebot ran JavaScript, yang adalah apa mendapatkan terindeks — plus JS console messages dan blocked resources. Jalankan Pengujian langsung untuk sebuah pada-demand render.
  • curl URL untuk see mentah, pre-JS HTML — sebuah empty shell berarti CSR dengan Tidak SSR.
  • Rich hasil Test validates data terstruktur.
  • Ahrefs situs Audit (JS rendering pada) dan Screaming Frog (JS mode) diff mentah vs. dirender DOM di scale.
  • Lighthouse / PageSpeed Insights untuk Core Web Vitals impact dari Anda rendering pilihan.

Angular adalah tidak buruk untuk SEO — ini adalah hanya berbeda. Mendapatkan nyata HTML ke respons, manage Anda head tags, pertahankan URLs dan tautan dapat di-crawl, dan let Google’s own alat arbitrate apa dirender. ini topic sits alongside JavaScript SEO dan headless-CMS rendering pertanyaan di ini cluster — underlying lesson adalah yang sama di seluruh semua dari them: rendering mode decides hampir semuanya.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.