SEO para SPA: mejores prácticas para aplicaciones de una sola página

Vadim Kravcenko
Vadim Kravcenko
· 6 min read

TL;DR: Las SPA rompen el SEO por defecto. Google pone en cola las páginas con JavaScript para renderizarlas — un proceso que puede tardar de horas a días, y los rastreadores de AI (GPTBot, ClaudeBot, PerplexityBot) ni siquiera ejecutan JavaScript. La solución es renderizar en el servidor con Next.js, Nuxt, Angular SSR o SvelteKit. Esta guía cubre la configuración exacta para cada framework, con código, pasos de prueba y el panorama del renderizado en 2026.

SEO para SPA: el problema es más grande de lo que crees

Las aplicaciones de una sola página cargan una plantilla HTML básica y luego la completan con JavaScript. El usuario obtiene una experiencia rápida, tipo app. Googlebot obtiene un <div id="app"></div> vacío.

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

He auditado cientos de SPA a través de SEOJuice. El patrón se repite: el sitio se ve precioso en el navegador, JavaScript se ejecuta perfectamente, y los motores de búsqueda no ven nada. O peor: ven el contenido días después, tras quedarse atascado en la cola de renderizado de Google. Solo el bug de URLs con hash en Angular les ha costado a clientes más tráfico orgánico que cualquier actualización de algoritmo que recuerde. Un cliente de ecommerce que usaba Angular con HashLocationStrategy tenía 1,200 páginas de producto. Google vio exactamente una página — la página de inicio. Todo lo que venía después del # era invisible. Eso no es una caída sutil en rankings. Eso es 60% de sus ingresos orgánicos, evaporados, por una configuración de enrutamiento que toma dos minutos arreglar una vez que sabes que existe.

Así funciona realmente el proceso de renderizado de Google:

  1. Rastreo — Googlebot solicita tu URL y recibe la respuesta HTML original
  2. Cola — Si la página necesita JavaScript, entra en una cola de renderizado
  3. Renderizado — El Web Rendering Service de Google (una instancia headless de Chromium) ejecuta JavaScript
  4. Indexación — El HTML renderizado se analiza para extraer contenido y enlaces

¿Esa cola entre el paso 2 y el paso 3? Puede tardar desde segundos hasta días. Tus competidores con HTML renderizado en el servidor se saltan la cola por completo — su contenido se indexa en el primer rastreo.

Y aún hay más. En 2025, Vercel analizó más de mil millones de solicitudes de rastreadores y encontró que la mayoría de los rastreadores de AI no ejecutan JavaScript en absoluto. GPTBot, ClaudeBot, PerplexityBot — leen HTML sin procesar. Un análisis de más de medio billón de solicitudes de GPTBot no encontró evidencia alguna de ejecución de JavaScript. Si tu SPA depende del renderizado del lado del cliente, tu contenido es invisible para los sistemas que impulsan ChatGPT, Claude y la búsqueda de Perplexity.

"Si tu sitio en Next.js entrega páginas críticas como SPA dependientes de JavaScript, esas páginas son inaccesibles para los sistemas que están moldeando cómo las personas descubren información."

— Vercel Engineering Blog (fuente)

Este no es un problema de nicho. Si quieres que tu contenido sea descubierto tanto por Google como por los motores de búsqueda con AI en 2026, renderizar en el servidor ya no es opcional — es un requisito previo.

SEO para SPA: CSR vs SSR vs SSG vs ISR

Hay cuatro formas de renderizar una aplicación de una sola página. La elección determina si los motores de búsqueda ven tu contenido de inmediato, más tarde o nunca.

EnfoqueCómo funcionaImpacto en SEOTiempo hasta el primer byte (TTFB)Ideal para
CSR (Client-Side Rendering)El navegador descarga una plantilla HTML básica y JavaScript construye la páginaMalo — Google la pone en cola para renderizar y los rastreadores de AI no ven nadaRápido (pero vacío)Dashboards internos, paneles de administración, páginas autenticadas
SSR (Server-Side Rendering)El servidor genera HTML completo por solicitud y envía la página terminadaExcelente — contenido completo en el primer rastreoVariable (tiempo de procesamiento del servidor)Contenido dinámico: ecommerce, noticias, contenido generado por usuarios
SSG (Static Site Generation)Las páginas se generan por adelantado en el despliegue como HTML estáticoExcelente — carga más rápida y totalmente rastreableLa más rápida (servida desde CDN)Blogs, documentación, páginas de marketing, páginas de aterrizaje
ISR (Incremental Static Regeneration)Páginas estáticas que se regeneran según un horario o bajo demandaExcelente — velocidad de SSG con contenido frescoRápido (cacheado con regeneración en segundo plano)Sitios grandes con contenido que cambia periódicamente (catálogos de productos, listados)

Conclusión clave

Cualquier página que quieras que Google o los motores de búsqueda con AI posicionen debe renderizarse en el servidor o generarse por adelantado. CSR está bien para páginas autenticadas y dashboards. Para todo lo público, usa SSR, SSG o ISR.

La regla es simple: si una URL necesita posicionar en búsqueda, debe entregar HTML completo en la respuesta inicial. Sin excepciones. Sin “pero Google ya renderiza JavaScript”. Google sí lo hace — a veces, eventualmente, de forma poco confiable, y los rastreadores de AI ni siquiera lo intentan. He tenido esta discusión con desarrolladores frontend más veces de las que puedo contar. La conversación normalmente termina cuando les muestro su sitio en la herramienta URL Inspection de Google y ven una página en blanco donde debería estar su hermosa interfaz.

SEO para SPA en React / Next.js

React puro (Create React App, Vite con React) es solo CSR. Google tendrá dificultades con eso. Next.js es la respuesta — y desde que App Router pasó a ser la configuración predeterminada en Next.js 13+, el panorama del SEO ha mejorado mucho.

React Server Components — el estándar por defecto en 2026

Con App Router, los componentes se renderizan en el servidor por defecto. Solo agregas 'use client' cuando un componente necesita APIs del navegador o interactividad. Eso significa que la mayor parte del contenido de tu página se entrega como HTML puro — sin depender del renderizado con JavaScript.

// app/blog/[slug]/page.tsx — Componente de servidor (predeterminado)
import { Metadata } from 'next'

// Metadatos dinámicos para cada post del blog
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}`,
    },
  }
}

// Este componente se ejecuta en el servidor — cero JS enviado al navegador
export default async function BlogPost({ params }) {
  const post = await getPost(params.slug)

  return (
    <article>
      <h1>{post.title}</h1>
      <div>{post.content}</div>
    </article>
  )
}

Generación estática con generateStaticParams

Para contenido que no cambia con frecuencia (posts de blog, páginas de aterrizaje), genera las páginas por adelantado durante la compilación:

// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await getAllPosts()
  return posts.map((post) => ({ slug: post.slug }))
}

// Combinado con el componente de página de arriba,
// Next.js genera HTML estático en build time para cada post

ISR para catálogos grandes

Para sitios de ecommerce con miles de productos, usa ISR para revalidar páginas según un horario:

// app/products/[id]/page.tsx
export const revalidate = 3600 // Regenera cada hora

export default async function ProductPage({ params }) {
  const product = await getProduct(params.id)
  return <ProductDetail product={product} />
}

Si estás atrapado en React puro y no puedes migrar a Next.js, usa un servicio de prerenderizado como Prerender.io como solución temporal. Pero entiende que esto es cinta adhesiva, no una solución real. Cada mes que retrasas la migración es un mes de indexación subóptima.

SEO para SPA en Vue / Nuxt 3

La misma historia, distinto ecosistema. Vue puro con Vue Router es solo CSR. Nuxt 3 te da SSR, SSG, ISR y edge rendering con Nitro — todo en un solo framework.

Renderizado universal (SSR por defecto)

Nuxt 3 usa renderizado universal desde el inicio. No necesitas configuración — tus páginas se renderizan en el servidor en la primera carga y luego se hidratan para la navegación del lado del cliente.

<!-- pages/blog/[slug].vue -->
<script setup>
const route = useRoute()
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`)

// Metadatos SEO por página
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>

Renderizado híbrido — distintas estrategias por ruta

Las routeRules de Nuxt 3 te permiten mezclar estrategias de renderizado dentro de la misma app. Esto es potentísimo para sitios que tienen tanto páginas estáticas de marketing como contenido dinámico:

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/':          { prerender: true },           // SSG — página de inicio
    '/blog/**':   { isr: 3600 },                 // ISR — posts del blog se regeneran cada hora
    '/products/**': { ssr: true },               // SSR — páginas de producto dinámicas
    '/dashboard/**': { ssr: false },             // CSR — dashboard autenticado
  }
})

Edge rendering con Nitro

Nitro, el motor de servidor de Nuxt 3, soporta despliegue en plataformas edge (Cloudflare Workers, Vercel Edge, Netlify Edge). Eso significa que tus páginas SSR se renderizan en ubicaciones edge del CDN cercanas al usuario — un TTFB por debajo de 50ms es realista. Para SEO, eso significa cargas más rápidas, mejores Core Web Vitals y rastreos más frecuentes por parte de Google.

SEO para SPA en Angular SSR

Históricamente, Angular ha sido el framework más difícil de optimizar para SEO. Eso cambió bastante desde Angular 17, que convirtió SSR en una capacidad de primera clase con soporte de hydration integrado. Ya no hace falta pegar Angular Universal como si fuera una ocurrencia de último minuto.

Cómo configurar SSR en Angular 17+

Los proyectos nuevos obtienen SSR por defecto cuando usas el CLI:

# Proyecto nuevo con SSR activado
ng new my-app --ssr

# Agrega SSR a un proyecto existente
ng add @angular/ssr

Meta tags dinámicos con los servicios de 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 });
    });
  }
}

Hydration incremental (Angular 19+)

Angular 19.2 introdujo hydration incremental, construyendo sobre la API @defer. Los componentes renderizan HTML completo en el servidor, pero solo se hidratan en el cliente cuando se activan (al entrar en viewport, al interactuar, etc.). Esto reduce el JavaScript enviado al navegador mientras mantiene todo el contenido SSR disponible para los rastreadores.

Trampa específica de Angular

El enrutamiento basado en hash (HashLocationStrategy) produce URLs como example.com/#/products. Google ignora todo lo que viene después del #. Tu catálogo de productos de 500 páginas parece una sola página. Cambia a PathLocationStrategy de inmediato — es la opción predeterminada en Angular, pero algunos proyectos legacy todavía usan hash routing. Este es exactamente el bug que le costó al cliente de ecommerce que mencioné arriba 60% de su tráfico orgánico. Llevaban dos años funcionando con hash routing. Dos años de páginas de producto que Google nunca supo que existían. El arreglo tomó 20 minutos. La recuperación tomó cuatro meses.

SEO para SPA en SvelteKit

SvelteKit se ha convertido silenciosamente en uno de los mejores frameworks para SEO desde el inicio. SSR viene activado por defecto — tendrías que desactivarlo activamente. El framework compila el framework fuera del resultado final, enviando mucho menos JavaScript que React o Angular.

SSR por defecto — sin configuración

Cada página de SvelteKit se renderiza en el servidor por defecto. Tus archivos +page.svelte generan HTML completo en la primera solicitud:

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

Renderizado híbrido por ruta

Como Nuxt, SvelteKit te permite controlar el renderizado por ruta:

// src/routes/blog/[slug]/+page.ts
export const prerender = true;  // SSG — generar en build time

// src/routes/dashboard/+page.ts
export const ssr = false;       // Solo CSR para contenido autenticado

Por qué SvelteKit merece atención para SEO: El compilador elimina el runtime del framework. Una página de SvelteKit envía una fracción del JavaScript que enviaría una página equivalente en Next.js o Nuxt. Menos JavaScript significa LCP más rápido, mejores puntuaciones de INP y Core Web Vitals más felices — todas señales de ranking.

Checklist de SEO para SPA

Toda SPA debe pasar estas verificaciones. Están ordenadas por impacto — arregla primero los puntos de arriba.

#VerificaciónPor qué importaCómo solucionarlo
1SSR o SSG activado para todas las páginas públicasSin eso, Google pone tus páginas en cola y los rastreadores de AI no ven nadaNext.js App Router, Nuxt 3, Angular SSR o SvelteKit
2URLs limpias (sin fragmentos hash)Las URLs con hash (#/page) son invisibles para los motores de búsquedaUsa enrutamiento basado en history — la opción predeterminada en todos los frameworks modernos
3Title tag único por páginaEl mismo título en cada ruta hace que Google elija uno e ignore el restogenerateMetadata (Next.js), useHead() (Nuxt), servicio Meta (Angular), <svelte:head>
4Meta description única por páginaControla tu snippet en los resultados de búsquedaLas mismas librerías que para title tags — configúralo por ruta
5Canonical tags en cada páginaEvita problemas de contenido duplicado por query params y trailing slashesAgrega <link rel="canonical"> por página en tus metadatos
6Jerarquía correcta de headings (H1 > H2 > H3)Le indica la estructura del contenido a los rastreadoresUn H1 por página y anidación lógica en los componentes
7Los enlaces internos usan etiquetas reales <a href>La navegación solo con JavaScript (handlers onClick) bloquea a los rastreadoresUsa componentes Link del framework: <Link>, <NuxtLink>, routerLink
8XML sitemap enviadoAyuda a Google a descubrir páginas a las que no se llega mediante enlacesGenéralo con next-sitemap, nuxt-simple-sitemap o tooling específico del framework
9Code splitting y lazy loadingReduce el bundle inicial de JS, mejora LCP e INPImports dinámicos (next/dynamic, defineAsyncComponent, @defer)
10Schema markup (JSON-LD) en páginas claveActiva rich snippets y ayuda a los rastreadores de AI a entender el contenidoJSON-LD en <head> o <body> — renderizado en el servidor, no inyectado vía JS

Errores comunes de SEO para SPA — con ejemplos de código

Estos son los errores que veo en casi todas las auditorías de SPA. Todos y cada uno destruyen rankings.

Error 1: depender de CSR para páginas públicas

“¡Pero Google renderiza JavaScript!” — sí, a veces, eventualmente, si tu JS no lanza un error, y si la cola de renderizado no está saturada, y si tu JavaScript no hace timeout, y si ninguno de tus scripts de terceros interfiere con el renderizado. Son demasiados “si” como para apostar tu tráfico orgánico ahí. Y los rastreadores de AI ni siquiera lo van a intentar.

// MAL — app de React solo con CSR
// Google ve: <div id="root"></div>
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);

// BIEN — Server Component de Next.js
// Google ve: HTML completamente renderizado con todo el contenido
export default async function Page() {
  const data = await fetchData();
  return <Article data={data} />;
}

Error 2: enrutamiento basado en hash

HashLocationStrategy de Angular y el modo hash de Vue Router producen URLs como example.com/#/products/shoes. Google ignora todo lo que viene después del #. Toda tu aplicación parece una sola página.

// MAL — modo hash de Vue Router
const router = createRouter({
  history: createWebHashHistory(),  // URLs: example.com/#/about
  routes
})

// BIEN — modo history de Vue Router
const router = createRouter({
  history: createWebHistory(),      // URLs: example.com/about
  routes
})

Error 3: el mismo title tag en cada página

Las SPA salen con un solo <title> en la plantilla HTML inicial. Si no lo actualizas dinámicamente por ruta, cada página tendrá el mismo título. Google indexará una versión e ignorará el resto.

<!-- MAL — plantilla HTML estática con un solo title -->
<!DOCTYPE html>
<html>
  <head>
    <title>My App</title>  <!-- El mismo para cada ruta -->
  </head>
  <body><div id="app"></div></body>
</html>

<!-- BIEN — metadatos dinámicos por ruta (ejemplo en Nuxt) -->
<script setup>
useHead({
  title: `${product.name} | MyStore`,
  meta: [{ name: 'description', content: product.summary }]
})
</script>

Error 4: errores de JavaScript que bloquean el renderizado

Un solo error no capturado en tu aplicación puede impedir que se renderice toda la página. El Web Rendering Service de Google no vuelve a intentarlo. La página se queda vacía en el índice.

Veo esto constantemente: un script de analytics de terceros lanza un error, o una respuesta faltante de la API rompe el árbol de componentes. ¿El resultado? Google indexa una página en blanco. Un cliente tenía un snippet de Hotjar que fallaba ocasionalmente en el renderer de Google. Sus páginas de producto aparecían aleatoriamente en blanco en la herramienta URL Inspection de GSC. La solución fue agregar un error boundary alrededor de la inicialización de analytics. Tomó 10 minutos. Llevaba meses dañando silenciosamente su indexación.

Solución: agrega error boundaries en React (componentes ErrorBoundary), usa NuxtErrorBoundary en Nuxt y prueba siempre con JavaScript desactivado (más sobre esto abajo).

Error 5: no tener sitemap

Las SPA con enrutamiento del lado del cliente no exponen su estructura de URLs mediante enlaces HTML como sí lo hacen los sitios multipágina. Sin un sitemap, Google descubre páginas solo a través de enlaces rastreables — y si tu enlazado interno depende de JavaScript, puede que no encuentre nada.

# Instala next-sitemap para Next.js
npm install next-sitemap

# next-sitemap.config.js
module.exports = {
  siteUrl: 'https://example.com',
  generateRobotsTxt: true,
  changefreq: 'weekly',
  // Excluye rutas que no deberían indexarse
  exclude: ['/dashboard/*', '/api/*', '/admin/*'],
}

Error 6: bloquear JavaScript en robots.txt

Si tu robots.txt bloquea archivos CSS o JS, el renderer de Google no puede construir tu página. Lo vemos sorprendentemente seguido — normalmente por una configuración predeterminada que quedó olvidada.

# MAL — bloqueando JS y CSS
User-agent: *
Disallow: /static/js/
Disallow: /static/css/

# BIEN — permitir todos los recursos necesarios para renderizar
User-agent: *
Disallow: /api/
Disallow: /dashboard/
Allow: /static/

Cómo probar el SEO de tu SPA paso a paso

Informe de auditoría de rendimiento de Google Lighthouse que muestra puntuaciones de Performance, Accessibility, Best Practices y SEO
Un informe de auditoría de rendimiento de Lighthouse. Las SPA cargadas de JavaScript suelen obtener puntuaciones más bajas en métricas de rendimiento debido a la sobrecarga del renderizado del lado del cliente. Fuente: Shopify

No asumas que tu SPA es rastreable solo porque funciona en Chrome. Así es como verificas lo que realmente ven los motores de búsqueda.

Prueba 1: URL Inspection de Google Search Console

La herramienta URL Inspection es tu mejor diagnóstico individual. Ingresa cualquier URL y haz clic en “Test Live URL”. Google solicitará tu página, la renderizará con su Web Rendering Service y te mostrará el resultado.

Qué debes revisar:

  • Pestaña Screenshot — ¿Muestra tu contenido real o una página en blanco / spinner de carga?
  • Pestaña Rendered HTML — ¿Tu contenido está en el DOM? Busca cadenas de texto clave.
  • Pestaña More Info — Revisa errores de consola de JavaScript. Cualquier error no capturado puede significar que el renderizado falló.
  • Page resources — Verifica que ningún archivo crítico de JS/CSS esté bloqueado o devolviendo errores.

Prueba 2: ver el HTML sin JavaScript

Abre tu página con JavaScript desactivado en el navegador o usa curl para inspeccionar la respuesta inicial:

curl -s https://example.com/product/123 | head -100

Si no ves el contenido principal, tienes un problema. Para páginas públicas, el HTML inicial debe incluir el título, el cuerpo del contenido, enlaces internos y metadatos clave. Si lo único que ves es un contenedor vacío y varios scripts, sigues dependiendo de CSR.

Prueba 3: usar la prueba de resultados enriquecidos o una auditoría de Lighthouse

La prueba de resultados enriquecidos de Google te ayuda a confirmar si el HTML renderizado contiene tus datos estructurados. Lighthouse, por su parte, te da una lectura rápida de rendimiento, accesibilidad y SEO técnico. No es una herramienta de indexación (y no sustituye a Search Console), pero sí detecta señales obvias de que tu SPA está enviando demasiado JavaScript o retrasando el contenido visible.

Prueba 4: ejecuta una auditoría SEO completa

Nuestra herramienta gratuita de auditoría SEO escanea tu SPA en busca de problemas de renderizado, meta tags faltantes, enlaces rotos y problemas de accesibilidad. Te muestra exactamente lo que ven los motores de búsqueda — sin login, con resultados en 30 segundos.

Prueba 5: revisa el acceso de los rastreadores de AI

Dado que los rastreadores de AI no renderizan JavaScript, revisa si pueden acceder a tu contenido usando el AI Crawler Inspector. Simula cómo GPTBot, ClaudeBot y otros bots de AI ven tus páginas.

SEO para SPA en 2026: qué cambió

El panorama del SEO para SPA en 2026 es materialmente distinto al de hace apenas dos años. Esto es lo que importa.

React Server Components son la nueva opción predeterminada

Con Next.js App Router, los componentes se renderizan en el servidor por defecto. Tú eliges explícitamente el renderizado del lado del cliente con 'use client'. Esto invierte el modelo viejo — en lugar de que todo sea CSR con SSR pegado encima, todo es SSR con CSR agregado donde hace falta. Las implicaciones para SEO son profundas: la mayor parte de tu aplicación se entrega automáticamente como HTML puro.

El edge rendering ya está listo para producción

Nuxt 3 con Nitro, Next.js Edge Runtime y los adapters de SvelteKit ahora despliegan SSR en ubicaciones edge del CDN (Cloudflare Workers, Vercel Edge Functions). Tus páginas se renderizan en el nodo edge más cercano al usuario — o al rastreador. Un TTFB por debajo de 50ms es alcanzable a nivel global.

Angular por fin tiene SSR de primera clase

Angular 17+ integró SSR en el CLI con ng new --ssr. Angular 19 agregó hydration incremental. Los días del doloroso setup de Angular Universal ya terminaron. Si todavía estás ejecutando una app Angular solo con CSR, el camino de migración ahora es bastante directo.

Los rastreadores de AI son un canal SEO real

GPTBot, ClaudeBot, PerplexityBot y otros están rastreando la web para construir datos de entrenamiento y alimentar la búsqueda con AI. Ninguno de ellos ejecuta JavaScript. El análisis de más de medio billón de solicitudes de GPTBot no encontró evidencia de ejecución de JS. Si quieres que tu contenido aparezca citado en respuestas generadas por AI, SSR es la única opción.

"Ver HTML renderizado, no solo el código fuente, es importante para diagnosticar si hay un problema de indexación. Google solo puede descubrir tus enlaces si son elementos HTML <a> con un atributo href."

— Martin Splitt, Developer Advocate en Google (fuente)

Core Web Vitals siguen importando

LCP, INP y CLS siguen siendo señales de ranking. Las SPA que envían bundles grandes de JavaScript son penalizadas en LCP (la página tarda demasiado en mostrar contenido significativo) e INP (las interacciones se sienten lentas). Code splitting, lazy loading y JavaScript mínimo del lado del cliente no son opcionales — son requisitos de rendimiento que impactan directamente los rankings.

"Pre-renderizar tu sitio de forma estática o en el servidor es la mejor práctica para SEO — hace que los rastreadores estén más dispuestos a reindexar tu sitio con mayor frecuencia."

— Vercel Engineering Blog (fuente)

Comparación rápida de frameworks para SEO en SPA

¿No tienes claro qué framework elegir? Así se comparan específicamente para SEO.

FunciónNext.js (React)Nuxt 3 (Vue)Angular SSRSvelteKit
SSR por defectoSí (App Router)Sí (desde v17)
Generación estáticagenerateStaticParamsprerender: trueng build --prerenderexport const prerender = true
Soporte para ISRIntegrado (revalidate)Integrado (isr: seconds)Manual vía service workerVía configuración específica del adapter
Edge renderingVercel Edge, CloudflareNitro (multiplataforma)LimitadoMúltiples adapters
API de metadatos por páginagenerateMetadatauseHead()Meta + servicios Title<svelte:head>
JavaScript del cliente enviadoModerado (RSC ayuda)ModeradoPesadoMínimo (compilado fuera)
Comunidad/ecosistemaLa más grandeSólidoEnfocado en enterpriseCreciendo rápido

Preguntas frecuentes

¿Google puede rastrear aplicaciones de una sola página?

Sí, pero con matices. El Web Rendering Service de Google usa un navegador headless Chromium para ejecutar JavaScript y renderizar SPA. Sin embargo, ese renderizado ocurre en una cola separada después del rastreo inicial, lo que puede retrasar la indexación de horas a días. Las páginas con errores de JavaScript pueden no renderizarse nunca. Para una indexación confiable, usa SSR o SSG — no dependas de la cola de renderizado de Google para contenido sensible al tiempo.

¿Una aplicación de una sola página es mala para SEO?

Una SPA solo con CSR sí es mala para SEO. Una SPA con renderizado en el servidor no lo es. El framework no importa — lo que importa es si la respuesta HTML inicial contiene tu contenido. Next.js, Nuxt, Angular SSR y SvelteKit producen SPA totalmente rastreables. El problema de “SPA vs. SEO” se resolvió hace años; el problema real son los desarrolladores que no implementan la solución.

¿Necesito renderizar en el servidor una app en React?

¿Para cualquier página que necesite posicionar en búsqueda? Sí. React por sí solo (vía Vite o Create React App) es solo CSR — los motores de búsqueda ven una página vacía. Next.js agrega SSR, SSG e ISR. Con React Server Components en App Router, la mayoría de los componentes se renderizan en el servidor por defecto. Si tu app en React sirve contenido público, Next.js es la solución estándar.

¿Cómo manejan las SPA los motores de búsqueda con AI?

No lo hacen. GPTBot (OpenAI), ClaudeBot (Anthropic), PerplexityBot y otros rastreadores de AI no ejecutan JavaScript. Solo analizan HTML original. El análisis de más de medio billón de solicitudes de GPTBot no encontró evidencia de renderizado con JavaScript. Si tu contenido se renderiza del lado del cliente, es invisible para los motores de búsqueda con AI. SSR es la única forma de aparecer en respuestas y citas generadas por AI.

¿Cuál es la diferencia entre SSR, SSG e ISR?

SSR (Server-Side Rendering) genera HTML en cada solicitud — ideal para contenido dinámico. SSG (Static Site Generation) genera HTML durante la compilación — es lo más rápido, pero requiere rebuilds cuando cambia el contenido. ISR (Incremental Static Regeneration) genera páginas estáticas que se regeneran automáticamente según un horario — combina la velocidad de SSG con contenido fresco. Los tres entregan HTML completo a los motores de búsqueda en la primera solicitud. Elige según la frecuencia con la que cambia tu contenido.

Conclusión

Las SPA no son inherentemente malas para SEO. Pero las SPA solo con CSR sí lo son y, en 2026, también son invisibles para los motores de búsqueda con AI.

La solución existe desde hace años. Next.js, Nuxt 3, Angular SSR y SvelteKit entregan HTML renderizado en el servidor desde el primer momento. React Server Components mejoró todavía más la configuración predeterminada — la mayor parte de tu app se renderiza automáticamente en el servidor. No hay excusa para lanzar una SPA pública sin renderizado en el servidor.

Si no estás seguro de si tu SPA es rastreable, haz una auditoría gratuita — toma 30 segundos y te muestra exactamente lo que ve Google. Para visibilidad ante rastreadores de AI, revisa el AI Crawler Inspector.

Lecturas relacionadas:

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

More articles

No related articles found.