SPAs and SEO Have a Complicated Relationship
Single-page applications built with React, Vue, or Angular create a tension with SEO. The app loads a minimal HTML shell and renders content with JavaScript. Googlebot can execute JavaScript, but it does so in a two-phase process with a queue delay. Content might not get indexed for days or weeks.
How Google Processes JavaScript Pages
- Crawl phase: Googlebot fetches the initial HTML shell and extracts links and basic metadata.
- Render phase: The page enters a rendering queue. When resources are available, Google executes the JavaScript and processes the fully rendered DOM.
The render queue introduces variable delay. A server-rendered page gets indexed in hours. An SPA page might wait 1-3 weeks.
Solution 1: Server-Side Rendering (SSR)
SSR renders full page HTML on the server. Googlebot receives complete HTML — no rendering queue delay.
Next.js (React)
# App Router — Server Components run on server by default
async function BlogPost({ params }) {
const article = await fetchArticle(params.slug);
return <article>{article.content}</article>;
}
# Pages Router — getServerSideProps
export async function getServerSideProps(context) {
const article = await fetchArticle(context.params.slug);
return { props: { article } };
}
Nuxt (Vue)
Provides SSR for Vue applications with similar concepts.
Angular Universal
More complex setup, but works reliably.
Solution 2: Static Site Generation (SSG)
Pre-render content at build time. The server hosts static HTML — fastest possible response for users and crawlers. Works best for sites under 10,000 pages.
Solution 3: Hybrid Rendering
Use SSR/SSG for pages needing SEO (marketing, blog, products) and client-side rendering for authenticated app pages (dashboard, settings). This is the approach I recommend for most SPA sites.
Common SPA SEO Mistakes
Hash-based routing: Googlebot doesn't follow hash fragments. Use HTML5 History API routing.
Missing meta tags in the shell: If your shell has generic title/description, that's what Google indexes if rendering fails.
Blocking resources in robots.txt: If JavaScript files are blocked, Googlebot can't render the page.
Lazy loading above-the-fold content: Content that loads only on scroll won't be seen by Googlebot.
Testing Your SPA's SEO
- GSC URL Inspection: Shows the rendered HTML Google sees
- Chrome DevTools with JS disabled: Shows what Googlebot's first pass sees
- Screaming Frog with JS rendering: Compare rendered vs raw HTML
Test after every major release. Framework updates can break SSR in ways invisible to regular users but devastating for SEO.