SEO per single-page application: best practice

Vadim Kravcenko
Vadim Kravcenko
· 6 min read

TL;DR: Per impostazione predefinita, le single-page application creano problemi SEO ai motori di ricerca. Google mette in coda le pagine JavaScript per il rendering — un processo che può richiedere da ore a giorni — e i crawler AI (GPTBot, ClaudeBot, PerplexityBot) non eseguono affatto JavaScript. La soluzione è il rendering lato server tramite Next.js, Nuxt, Angular SSR o SvelteKit. In questa guida trovi la configurazione esatta per ogni framework, con codice, passaggi di test e il panorama del rendering nel 2026.

Le single-page application hanno un problema SEO — ed è più grande di quanto pensi

Le single-page application caricano un guscio HTML iniziale e poi lo riempiono con JavaScript. Per l’utente l’esperienza è veloce, quasi da app nativa. Googlebot, invece, spesso riceve nient’altro che un semplice <div id="app"></div> vuoto.

Client-side vs server-side JavaScript rendering comparison using the hamburger analogy
Client-side vs server-side rendering — choosing the right approach for SEO. Source: Lumar
Diagram showing how client-side JavaScript rendering works in single-page applications
How client-side JavaScript rendering works — and why it causes SEO problems. Source: Lumar

Ho fatto audit su centinaia di single-page application tramite SEOJuice. La dinamica è sempre la stessa: il sito è bellissimo nel browser, JavaScript gira alla perfezione, e i motori di ricerca non vedono quasi nulla. O peggio — vedono i contenuti giorni dopo, dopo essere rimasti bloccati nella coda di rendering di Google. Il bug degli URL hash in Angular, da solo, è costato ai clienti più traffico organico di qualsiasi aggiornamento dell’algoritmo che io ricordi. Un cliente ecommerce che usava Angular con HashLocationStrategy aveva 1,200 pagine prodotto. Google ne vedeva esattamente una: la pagina iniziale. Tutto ciò che veniva dopo il # era invisibile. Non è un piccolo calo di ranking. È il 60% del loro fatturato organico sparito per una configurazione di routing che richiede due minuti per essere corretta, se sai dove guardare.

Ecco come funziona davvero la pipeline di rendering di Google:

  1. Scansione — Googlebot recupera il tuo URL e riceve la risposta HTML grezza
  2. Coda — Se la pagina richiede JavaScript, entra in una coda di rendering
  3. Rendering — Il Web Rendering Service di Google (un’istanza headless di Chromium) esegue JavaScript
  4. Indicizzazione — L’HTML renderizzato viene analizzato per contenuti e link

Quella coda tra il passaggio 2 e il passaggio 3? Può richiedere da pochi secondi a giorni. I tuoi competitor che servono HTML lato server la saltano del tutto — i loro contenuti possono essere indicizzati già al primo crawl.

Ma c’è di peggio. Nel 2025, Vercel ha analizzato oltre un miliardo di richieste dei crawler e ha scoperto che la maggior parte dei crawler AI non esegue affatto JavaScript. GPTBot, ClaudeBot, PerplexityBot — leggono HTML grezzo, non renderizzato. Un’analisi di oltre mezzo miliardo di fetch di GPTBot non ha trovato alcuna evidenza di esecuzione JavaScript. Se la tua single-page application si basa sul rendering lato client, i tuoi contenuti sono invisibili ai sistemi che alimentano ChatGPT, Claude e la ricerca di Perplexity.

"Se il tuo sito Next.js serve pagine critiche come SPA dipendenti da JavaScript, quelle pagine sono inaccessibili ai sistemi che stanno plasmando il modo in cui le persone scoprono le informazioni."

— Vercel Engineering Blog (fonte)

Non è un problema di nicchia. Se vuoi che i tuoi contenuti vengano scoperti sia da Google sia dai motori di ricerca AI nel 2026, il rendering lato server non è più opzionale — è un prerequisito.

SEO per single-page application: CSR vs SSR vs SSG vs ISR

Ci sono quattro modi per renderizzare una single-page application. La scelta determina se i motori di ricerca vedranno i tuoi contenuti subito, più tardi o mai.

ApproccioCome funzionaImpatto SEOTempo al primo byte (TTFB)Ideale per
CSR (Client-Side Rendering)Il browser scarica un guscio HTML vuoto, poi JavaScript compone la paginaScarso — Google mette in coda il rendering, i crawler AI non vedono nullaVeloce (ma vuoto)Dashboard interne, pannelli admin, pagine protette da login
SSR (Server-Side Rendering)Il server genera HTML completo per ogni richiesta e invia la pagina già prontaEccellente — contenuto completo già al primo crawlVariabile (dipende dal tempo di elaborazione del server)Contenuti dinamici: e-commerce, news, contenuti generati dagli utenti
SSG (Static Site Generation)Le pagine vengono generate in anticipo al deploy come HTML staticoEccellente — caricamento rapidissimo, completamente scansionabileIl più veloce (servito da CDN)Blog, documentazione, pagine marketing, landing page
ISR (Incremental Static Regeneration)Pagine statiche che si rigenerano a intervalli o on-demandEccellente — velocità di SSG con contenuti sempre freschiVeloce (cache con rigenerazione in background)Siti grandi con contenuti che cambiano periodicamente (cataloghi prodotto, pagine elenco)

Punto chiave

Qualsiasi pagina che vuoi far posizionare su Google o sui motori di ricerca AI deve essere renderizzata lato server o generata in anticipo. Il CSR va bene per pagine protette da login e dashboard. Per tutto ciò che è pubblico, usa SSR, SSG o ISR.

La regola è semplice: se un URL deve posizionarsi in ricerca, deve restituire HTML completo nella risposta iniziale. Nessuna eccezione. E no, non vale il solito “tanto Google ormai renderizza JavaScript”. Sì, Google ci prova — a volte, prima o poi, in modo poco affidabile — e i crawler AI non ci provano nemmeno. Ho avuto questa discussione con sviluppatori frontend più volte di quante riesca a contare. Di solito la conversazione finisce quando mostro il loro sito nello strumento Controllo URL di Google e vedono una pagina vuota dove dovrebbe esserci la loro splendida UI.

SEO per single-page application con React / Next.js

React puro (Create React App, Vite con React) è solo CSR. Google farà fatica a interpretarlo e indicizzarlo correttamente. Next.js è la risposta — e da quando App Router è diventato l’impostazione predefinita in Next.js 13+, dal punto di vista SEO le cose sono migliorate molto.

React Server Components — Lo standard del 2026

Con App Router, i componenti vengono renderizzati lato server per impostazione predefinita. Aggiungi 'use client' solo quando un componente ha bisogno delle API del browser o di interattività. Questo significa che la maggior parte del contenuto della tua pagina viene servita come HTML puro — senza dipendere dal rendering JavaScript nel browser.

// 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>
  )
}

Generazione statica con generateStaticParams

Per contenuti che non cambiano spesso (articoli del blog, landing page), genera le pagine in anticipo in fase di build:

// 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

ISR per cataloghi grandi

Per siti ecommerce con migliaia di prodotti, usa ISR per rivalidare le pagine a intervalli programmati:

// 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} />
}

Se sei bloccato su React puro e non puoi migrare a Next.js, usa un servizio di pre-rendering come Prerender.io come soluzione tampone. Ma capisci bene una cosa: è nastro adesivo, non una vera soluzione. Ogni mese in cui rimandi la migrazione è un mese di indicizzazione subottimale.

SEO per single-page application con Vue / Nuxt 3

Stessa storia, ecosistema diverso. Vue puro con Vue Router è solo CSR. Nuxt 3 ti offre SSR, SSG, ISR ed edge rendering con Nitro — tutto in un unico framework.

Universal Rendering (SSR di default)

Nuxt 3 usa l’universal rendering già pronto. Nessuna configurazione necessaria — le tue pagine vengono renderizzate lato server al primo caricamento, poi idratate per la navigazione lato client.

<!-- 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>

Hybrid Rendering — Strategie diverse per route diverse

Le routeRules di Nuxt 3 ti permettono di mescolare strategie di rendering nella stessa app. È molto potente per siti che hanno sia pagine marketing statiche sia contenuti dinamici:

// 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
  }
})

Edge Rendering con Nitro

Nitro, il motore server di Nuxt 3, supporta il deploy su piattaforme edge (Cloudflare Workers, Vercel Edge, Netlify Edge). Questo significa che le tue pagine SSR vengono renderizzate nei nodi CDN più vicini all’utente — un TTFB sotto i 50ms è realistico. Dal punto di vista SEO, significa caricamenti più rapidi, Core Web Vitals migliori e crawl più frequenti da parte di Google.

SEO per single-page application con Angular SSR

Storicamente Angular è stato il framework più difficile da ottimizzare per la SEO. La situazione è cambiata parecchio da Angular 17, che ha reso SSR un cittadino di prima classe con supporto integrato per l’hydration. Niente più Angular Universal appiccicato sopra come ripensamento.

Configurare SSR in Angular 17+

I nuovi progetti ottengono SSR di default quando usi la CLI:

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

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

Meta tag dinamici con i servizi di Angular

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

Incremental Hydration (Angular 19+)

Angular 19.2 ha introdotto l’incremental hydration, basandosi sull’API @defer. I componenti generano HTML completo sul server ma vengono idratati sul client solo quando scatta un trigger (nel viewport, all’interazione, ecc.). Questo riduce il JavaScript inviato al browser mantenendo comunque tutto il contenuto SSR disponibile ai crawler.

Problema tipico specifico di Angular

Il routing basato su hash (HashLocationStrategy) produce URL come example.com/#/products. Google ignora tutto ciò che viene dopo il #. Il tuo catalogo prodotti da 500 pagine appare come una sola pagina. Passa subito a PathLocationStrategy — è il default in Angular, ma alcuni progetti legacy usano ancora l’hash routing. È esattamente il bug che è costato al cliente ecommerce citato sopra il 60% del traffico organico. Erano andati avanti con hash routing per due anni. Due anni di pagine prodotto che Google non sapeva nemmeno esistessero. La correzione ha richiesto 20 minuti. Il recupero, quattro mesi.

SEO per single-page application con SvelteKit

SvelteKit è diventato in silenzio uno dei migliori framework per la SEO pronti all’uso. SSR è attivo di default — dovresti proprio disattivarlo volontariamente. Inoltre il framework compila via il framework stesso, spedendo molto meno JavaScript rispetto a React o Angular.

SSR di default — Nessuna configurazione necessaria

Ogni pagina SvelteKit viene renderizzata lato server per impostazione predefinita. I tuoi file +page.svelte generano HTML completo alla prima richiesta:

<!-- 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 };
}

Hybrid Rendering per route

Come Nuxt, anche SvelteKit ti permette di controllare il rendering per singola route:

// 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

Perché SvelteKit merita attenzione lato SEO: il compilatore elimina il runtime del framework. Una pagina SvelteKit invia una frazione del JavaScript rispetto a una pagina equivalente in Next.js o Nuxt. Meno JavaScript significa LCP più veloce, punteggi INP migliori e Core Web Vitals più sani — tutti segnali di ranking.

La checklist SEO per le single-page application

Ogni single-page application deve superare questi controlli. Sono ordinati per impatto — sistema prima gli elementi in alto.

#ControlloPerché contaCome risolvere
1SSR o SSG attivi su tutte le pagine pubblicheSenza, Google mette in coda le tue pagine e i crawler AI non vedono nullaNext.js App Router, Nuxt 3, Angular SSR o SvelteKit
2URL puliti (senza frammenti hash)Gli URL hash (#/page) sono invisibili ai motori di ricercaUsa routing basato sulla history — l’impostazione predefinita in tutti i framework moderni
3Title tag unico per paginaLo stesso title su ogni route significa che Google ne sceglie uno e ignora gli altrigenerateMetadata (Next.js), useHead() (Nuxt), servizio Meta (Angular), <svelte:head>
4Meta description unica per paginaControlla il tuo snippet nei risultati di ricercaStesse librerie dei title tag — impostala per route
5Canonical tag su ogni paginaPreviene problemi di contenuto duplicato causati da query param e trailing slashAggiungi <link rel="canonical"> per pagina nei metadata
6Gerarchia corretta degli heading (H1 > H2 > H3)Segnala la struttura del contenuto ai crawlerUn solo H1 per pagina, nesting logico nei componenti
7I link interni usano veri tag <a href>La navigazione solo JavaScript (handler onClick) blocca i crawlerUsa i componenti Link del framework: <Link>, <NuxtLink>, routerLink
8Sitemap XML inviataAiuta Google a scoprire pagine non raggiungibili tramite linkGenerala con next-sitemap, nuxt-simple-sitemap o tool specifici del framework
9Code splitting e lazy loadingRiduce il bundle JS iniziale, migliora LCP e INPImport dinamici (next/dynamic, defineAsyncComponent, @defer)
10Schema markup (JSON-LD) sulle pagine chiaveAbilita rich snippet e aiuta i crawler AI a capire il contenutoJSON-LD nel <head> o nel <body> — renderizzato lato server, non iniettato via JS

Errori SEO comuni nelle single-page application — con esempi di codice

Questi sono gli errori che vedo in quasi ogni audit di single-page application. Ognuno di loro, senza eccezioni, distrugge il ranking.

Errore 1: Affidarsi al CSR per le pagine pubbliche

“Ma Google renderizza JavaScript!” — sì, a volte, prima o poi, se il tuo JS non genera errori, se la coda di rendering non è intasata, se JavaScript non va in timeout e se nessuno script di terze parti interferisce con il rendering. Sono un bel po’ di “se” su cui scommettere il tuo traffico organico. E i crawler AI non ci provano nemmeno.

// 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} />;
}

Errore 2: Routing basato su hash

HashLocationStrategy di Angular e la modalità hash di Vue Router producono URL come example.com/#/products/shoes. Google ignora tutto ciò che viene dopo il #. L’intera applicazione appare come una sola pagina.

// 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
})

Errore 3: Lo stesso title tag su ogni pagina

Le single-page application partono con un solo <title> nel guscio HTML iniziale. Se non lo aggiorni dinamicamente per ogni route, ogni pagina avrà lo stesso title. Google indicizzerà una versione e ignorerà le altre.

<!-- 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>

Errore 4: Errori JavaScript che bloccano il rendering

Un singolo errore non gestito nella tua applicazione può impedire il rendering dell’intera pagina. Il Web Rendering Service di Google non riprova. La pagina resta vuota nell’indice.

Lo vedo continuamente: uno script analytics di terze parti genera un errore, oppure una risposta API mancante manda in crash l’albero dei componenti. Il risultato? Google indicizza una pagina vuota. Un cliente aveva uno snippet Hotjar che occasionalmente falliva nel renderer di Google. Le loro pagine prodotto apparivano casualmente vuote nello strumento Controllo URL di GSC. La soluzione è stata aggiungere un error boundary attorno all’inizializzazione degli analytics. Tempo richiesto: 10 minuti. Aveva danneggiato silenziosamente la loro indicizzazione per mesi.

Soluzione: aggiungi error boundary in React (componenti ErrorBoundary), usa NuxtErrorBoundary in Nuxt e testa sempre con JavaScript disattivato (ci arrivo tra poco).

Errore 5: Nessuna sitemap

Le single-page application con routing lato client non espongono la loro struttura URL tramite link HTML come fanno i siti multipagina. Senza sitemap, Google scopre le pagine solo tramite link scansionabili — e se il tuo internal linking è guidato da JavaScript, potrebbe non trovare nulla.

# 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/*'],
}

Errore 6: Bloccare JavaScript in robots.txt

Se il tuo robots.txt blocca file CSS o JS, il renderer di Google non può costruire la tua pagina. Lo vediamo sorprendentemente spesso — di solito è una configurazione predefinita rimasta lì per sbaglio.

# 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/

Come testare la SEO della tua single-page application passo dopo passo

Report di audit delle prestazioni di Google Lighthouse che mostra i punteggi per Performance, Accessibility, Best Practices e SEO
Un report di audit delle prestazioni di Lighthouse. Le single-page application pesanti in JavaScript spesso ottengono punteggi più bassi nelle metriche di performance a causa dell’overhead del rendering lato client. Fonte: Shopify

Non dare per scontato che la tua single-page application sia scansionabile solo perché funziona in Chrome. Ecco come verificare cosa vedono davvero i motori di ricerca.

Test 1: Controllo URL in Google Search Console

Lo strumento Controllo URL è la tua migliore diagnostica in assoluto. Inserisci un URL qualsiasi e clicca su “Test URL pubblicato”. Google recupererà la tua pagina, la renderizzerà con il suo Web Rendering Service e ti mostrerà il risultato.

Cosa controllare:

  • Scheda Screenshot — mostra davvero il tuo contenuto o una pagina vuota / uno spinner di caricamento?
  • Scheda HTML renderizzato — il tuo contenuto è nel DOM? Cerca stringhe di testo chiave.
  • Scheda Maggiori informazioni — controlla eventuali errori JavaScript nella console. Qualsiasi errore non gestito può significare che il rendering è fallito.
  • Risorse della pagina — verifica che nessun file JS/CSS critico sia bloccato o restituisca errori.

Test 4: Esegui un audit SEO completo

Il nostro tool gratuito di audit SEO analizza la tua single-page application alla ricerca di problemi di rendering, meta tag mancanti, link rotti e problemi di accessibilità. Ti mostra esattamente cosa vedono i motori di ricerca — senza login, risultati in 30 secondi.

Test 5: Controlla l’accesso dei crawler AI

Dato che i crawler AI non renderizzano JavaScript, verifica se riescono ad accedere ai tuoi contenuti usando l’AI Crawler Inspector. Simula il modo in cui GPTBot, ClaudeBot e altri bot AI vedono le tue pagine.

SEO per single-page application nel 2026: cosa è cambiato

Il panorama SEO delle single-page application nel 2026 è sostanzialmente diverso rispetto anche solo a due anni fa. Ecco cosa conta davvero.

React Server Components sono il nuovo default

Con Next.js App Router, i componenti vengono renderizzati lato server per impostazione predefinita. Passi esplicitamente al rendering lato client con 'use client'. Questo ribalta il vecchio modello — invece di avere tutto in CSR con SSR aggiunto sopra, hai tutto in rendering lato server con il lato client aggiunto solo dove serve. Le implicazioni SEO sono enormi: gran parte della tua applicazione viene servita automaticamente come HTML puro.

L’edge rendering è pronto per la produzione

Nuxt 3 con Nitro, Next.js Edge Runtime e gli adapter di SvelteKit ora distribuiscono SSR nei nodi edge della CDN (Cloudflare Workers, Vercel Edge Functions). Le tue pagine vengono renderizzate nel nodo edge più vicino all’utente — o al crawler. Un TTFB sotto i 50ms è raggiungibile a livello globale.

Angular ha finalmente un SSR di prima classe

Angular 17+ ha integrato SSR nella CLI con ng new --ssr. Angular 19 ha aggiunto l’incremental hydration. I tempi delle configurazioni dolorose di Angular Universal sono finiti. Se stai ancora usando un’app Angular basata esclusivamente su CSR, oggi il percorso di migrazione è finalmente lineare.

I crawler AI sono un vero canale SEO

GPTBot, ClaudeBot, PerplexityBot e altri stanno crawlando il web per costruire dati di training e alimentare la ricerca AI. Nessuno di loro esegue JavaScript. L’analisi di oltre mezzo miliardo di richieste GPTBot non ha trovato alcuna evidenza di esecuzione JS. Se vuoi che i tuoi contenuti vengano citati nelle risposte generate dall’AI, SSR è l’unica opzione.

"Vedere l’HTML renderizzato, non solo il codice sorgente, è importante per diagnosticare se c’è un problema di indicizzazione. Google può scoprire i tuoi link solo se sono elementi HTML <a> con un attributo href."

— Martin Splitt, Developer Advocate at Google (fonte)

I Core Web Vitals contano ancora

LCP, INP e CLS restano segnali di ranking. Le single-page application che distribuiscono bundle JavaScript pesanti vengono penalizzate su LCP (la pagina impiega troppo a mostrare contenuti significativi) e su INP (le interazioni risultano lente). Code splitting, lazy loading e JavaScript lato client ridotto al minimo non sono opzionali — sono requisiti di performance che impattano direttamente il ranking.

"Il prerendering statico o lato server del tuo sito è la best practice per la SEO — rende i crawler più propensi a reindicizzare il tuo sito più frequentemente."

— Vercel Engineering Blog (fonte)

Confronto rapido tra framework

Non sai quale framework scegliere? Ecco come si confrontano dal punto di vista SEO.

FunzionalitàNext.js (React)Nuxt 3 (Vue)Angular SSRSvelteKit
SSR di defaultSì (App Router)Sì (dalla v17)
Generazione staticagenerateStaticParamsprerender: trueng build --prerenderexport const prerender = true
Supporto ISRIntegrato (revalidate)Integrato (isr: seconds)Manuale tramite service workerTramite configurazione specifica dell’adapter
Edge renderingVercel Edge, CloudflareNitro (multi-platform)LimitatoPiù adapter
API metadata per paginagenerateMetadatauseHead()Servizi Meta + Title<svelte:head>
JavaScript client distribuitoModerato (RSC aiuta)ModeratoPesanteMinimo (compilato via)
Community/ecosistemaIl più grandeSolidoOrientato enterpriseIn rapida crescita

Domande frequenti

Google può crawlare le single-page application?

Sì, ma con riserve. Il Web Rendering Service di Google usa un browser Chromium headless per eseguire JavaScript e renderizzare le single-page application. Tuttavia questo rendering avviene in una coda separata dopo il crawl iniziale, e può ritardare l’indicizzazione da ore a giorni. Le pagine con errori JavaScript potrebbero non essere mai renderizzate. Per un’indicizzazione affidabile, usa SSR o SSG — non affidarti alla coda di rendering di Google per contenuti sensibili al fattore tempo.

Una single-page application fa male alla SEO?

Una single-page application basata esclusivamente su CSR fa male alla SEO. Una single-page application con rendering lato server no. Il framework non è il punto — conta se la risposta HTML iniziale contiene o no i tuoi contenuti. Next.js, Nuxt, Angular SSR e SvelteKit producono tutti SPA completamente scansionabili. Il problema “SPA vs SEO” è stato risolto anni fa; il vero problema sono gli sviluppatori che non implementano la soluzione.

Mi serve il rendering lato server per un’app React?

Per qualsiasi pagina che deve posizionarsi in ricerca? Sì. React da solo (tramite Vite o Create React App) è solo CSR — i motori di ricerca vedono una pagina vuota. Next.js aggiunge SSR, SSG e ISR. Con React Server Components in App Router, la maggior parte dei componenti viene renderizzata lato server di default. Se la tua app React serve contenuti pubblici, Next.js è la soluzione standard.

Come gestiscono le SPA i motori di ricerca AI?

Non le gestiscono. GPTBot (OpenAI), ClaudeBot (Anthropic), PerplexityBot e altri crawler AI non eseguono JavaScript. Analizzano solo HTML grezzo. L’analisi di oltre mezzo miliardo di richieste GPTBot non ha trovato alcuna evidenza di rendering JavaScript. Se i tuoi contenuti sono renderizzati lato client, sono invisibili ai motori di ricerca AI. SSR è l’unico modo per comparire nelle risposte e nelle citazioni generate dall’AI.

Qual è la differenza tra SSR, SSG e ISR?

SSR (Server-Side Rendering) genera HTML a ogni richiesta — ideale per contenuti dinamici. SSG (Static Site Generation) genera HTML in fase di build — è il più veloce ma richiede nuove build quando i contenuti cambiano. ISR (Incremental Static Regeneration) genera pagine statiche che si rigenerano automaticamente a intervalli — combina la velocità di SSG con contenuti aggiornati. Tutti e tre consegnano HTML completo ai motori di ricerca già alla prima richiesta. Scegli in base a quanto spesso cambiano i tuoi contenuti.

In sintesi

Le single-page application non sono intrinsecamente negative per la SEO. Ma le SPA basate esclusivamente su CSR sì, e nel 2026 sono invisibili anche ai motori di ricerca AI.

La soluzione esiste da anni. Next.js, Nuxt 3, Angular SSR e SvelteKit forniscono tutti HTML lato server già pronto. React Server Components ha reso il default ancora migliore — gran parte della tua app viene renderizzata automaticamente sul server. Non c’è alcuna scusa per pubblicare una single-page application accessibile al pubblico senza rendering lato server.

Se non sei sicuro che la tua single-page application sia scansionabile, fai un audit gratuito — richiede 30 secondi e ti mostra esattamente cosa vede Google. Per la visibilità verso i crawler AI, controlla l’AI Crawler Inspector.

Letture correlate:

SEOJuice
Stay visible everywhere
Get discovered across Google and AI platforms with research-based optimizations.
Works with any CMS
Automated Internal Links
On-Page SEO Optimizations
Get Started Free

no credit card required