SEO para aplicaciones JavaScript
Frameworks como React, Vue y Angular crean contenido dinámico que puede ser difícil de rastrear. Entender las estrategias de renderizado es clave para el SEO en JavaScript.
Estrategias de renderizado
CSR - Client-Side Rendering
JavaScript renderiza el contenido en el navegador
Reto SEO: los motores pueden no ver el contenido
SSR - Server-Side Rendering
El servidor genera HTML por cada request
Beneficio SEO: contenido completo inmediato
SSG - Static Site Generation
HTML generado en build time
Beneficio SEO: páginas rápidas y renderizadas
ISR - Incremental Static Regeneration
Páginas estáticas que se actualizan periódicamente
Beneficio SEO: contenido fresco con rendimiento estático
Configuración SEO en Next.js
// app/layout.tsx - Global metadata
import type { Metadata } from 'next';
export const metadata: Metadata = {
metadataBase: new URL('https://example.com'),
title: {
template: '%s | Site Name',
default: 'Site Name - Description',
},
description: 'Site description',
openGraph: {
type: 'website',
locale: 'en_US',
siteName: 'Site Name',
},
twitter: {
card: 'summary_large_image',
creator: '@handle',
},
robots: {
index: true,
follow: true,
},
};
// app/blog/[slug]/page.tsx - Dynamic metadata
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,
images: [post.image],
},
};
}
Generación estática para SEO
// Generate static paths at build time
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((post) => ({
slug: post.slug,
}));
}
// Page component with data
export default async function BlogPost({ params }) {
const post = await getPost(params.slug);
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}
// ISR - Revalidate every hour
export const revalidate = 3600;
Problemas comunes de SEO en JavaScript
Problemas:
- Contenido cargado después del render inicial
- Enlaces con onClick en lugar de href
- Scroll infinito sin paginación
- Contenido detrás de interacciones del usuario
- Bundles de JavaScript pesados
Soluciones:
- Usa SSR/SSG para contenido crítico
- Usa etiquetas <a> con href
- Implementa "load more" con URLs
- Renderiza en servidor contenido importante
- Code splitting y lazy loading
Probar el renderizado JavaScript
// Test what Google sees
// 1. Google Search Console - URL Inspection
// Shows rendered HTML as Googlebot sees it
// 2. Chrome DevTools - Disable JavaScript
// Settings > Debugger > Disable JavaScript
// Check if critical content is visible
// 3. View source vs Inspect Element
// View source = what crawlers see initially
// Inspect = rendered DOM after JS
// 4. Fetch as Google / URL Inspection Tool
// Submit URLs to see crawled version