Generación de Sitios Estáticos (SSG)

Ejemplos

Si una página utiliza Generación Estática, el HTML de la página se genera en tiempo de compilación. Esto significa que en producción, el HTML de la página se genera cuando ejecutas next build. Este HTML luego se reutiliza en cada solicitud y puede ser almacenado en caché por una CDN.

En Next.js, puedes generar páginas estáticamente con o sin datos. Veamos cada caso.

Generación Estática sin datos

Por defecto, Next.js prerrenderiza páginas usando Generación Estática sin obtener datos. Aquí un ejemplo:

function About() {
  return <div>About</div>
}

export default About

Nota que esta página no necesita obtener datos externos para ser prerrenderizada. En casos como este, Next.js genera un único archivo HTML por página durante el tiempo de compilación.

Generación Estática con datos

Algunas páginas requieren obtener datos externos para el prerrenderizado. Hay dos escenarios, y uno o ambos pueden aplicarse. En cada caso, puedes usar estas funciones que proporciona Next.js:

  1. El contenido de tu página depende de datos externos: Usa getStaticProps.
  2. Las rutas de tu página dependen de datos externos: Usa getStaticPaths (usualmente junto con getStaticProps).

Escenario 1: El contenido de tu página depende de datos externos

Ejemplo: Tu página de blog podría necesitar obtener la lista de publicaciones desde un CMS (sistema de gestión de contenidos).

// TODO: Necesito obtener `posts` (llamando a algún endpoint API)
//       antes de que esta página pueda ser prerrenderizada.
export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

Para obtener estos datos durante el prerrenderizado, Next.js te permite exportar una función async llamada getStaticProps desde el mismo archivo. Esta función se llama en tiempo de compilación y te permite pasar los datos obtenidos a los props de la página durante el prerrenderizado.

export default function Blog({ posts }) {
  // Renderizar posts...
}

// Esta función se llama en tiempo de compilación
export async function getStaticProps() {
  // Llama a un endpoint API externo para obtener posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // Al devolver { props: { posts } }, el componente Blog
  // recibirá `posts` como prop en tiempo de compilación
  return {
    props: {
      posts,
    },
  }
}

Para aprender más sobre cómo funciona getStaticProps, consulta la documentación de Obtención de Datos.

Escenario 2: Las rutas de tu página dependen de datos externos

Next.js te permite crear páginas con rutas dinámicas. Por ejemplo, puedes crear un archivo llamado pages/posts/[id].js para mostrar una publicación de blog basada en id. Esto te permitirá mostrar una publicación con id: 1 cuando accedas a posts/1.

Para aprender más sobre rutas dinámicas, consulta la documentación de Enrutamiento Dinámico.

Sin embargo, qué id quieres prerrenderizar en tiempo de compilación podría depender de datos externos.

Ejemplo: supón que solo has añadido una publicación de blog (con id: 1) a la base de datos. En este caso, solo querrías prerrenderizar posts/1 en tiempo de compilación.

Más tarde, podrías añadir una segunda publicación con id: 2. Entonces también querrías prerrenderizar posts/2.

Así que las rutas de tu página que se prerrenderizan dependen de datos externos. Para manejar esto, Next.js te permite exportar una función async llamada getStaticPaths desde una página dinámica (pages/posts/[id].js en este caso). Esta función se llama en tiempo de compilación y te permite especificar qué rutas quieres prerrenderizar.

// Esta función se llama en tiempo de compilación
export async function getStaticPaths() {
  // Llama a un endpoint API externo para obtener posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // Obtiene las rutas que queremos prerrenderizar basadas en posts
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  // Prerrenderizaremos solo estas rutas en tiempo de compilación.
  // { fallback: false } significa que otras rutas deberían devolver 404.
  return { paths, fallback: false }
}

También en pages/posts/[id].js, necesitas exportar getStaticProps para que puedas obtener los datos sobre la publicación con este id y usarlos para prerrenderizar la página:

export default function Post({ post }) {
  // Renderizar publicación...
}

export async function getStaticPaths() {
  // ...
}

// Esto también se llama en tiempo de compilación
export async function getStaticProps({ params }) {
  // params contiene el `id` de la publicación.
  // Si la ruta es como /posts/1, entonces params.id es 1
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()

  // Pasa los datos de la publicación a la página via props
  return { props: { post } }
}

Para aprender más sobre cómo funciona getStaticPaths, consulta la documentación de Obtención de Datos.

¿Cuándo debería usar Generación Estática?

Recomendamos usar Generación Estática (con y sin datos) siempre que sea posible porque tu página puede construirse una vez y servirse desde una CDN, lo que la hace mucho más rápida que tener un servidor renderizando la página en cada solicitud.

Puedes usar Generación Estática para muchos tipos de páginas, incluyendo:

  • Páginas de marketing
  • Publicaciones de blog y portafolios
  • Listados de productos de e-commerce
  • Ayuda y documentación

Deberías preguntarte: "¿Puedo prerrenderizar esta página antes de la solicitud de un usuario?" Si la respuesta es sí, entonces deberías elegir Generación Estática.

Por otro lado, la Generación Estática no es una buena idea si no puedes prerrenderizar una página antes de la solicitud de un usuario. Tal vez tu página muestra datos actualizados frecuentemente, y el contenido de la página cambia en cada solicitud.

En casos como este, puedes hacer una de las siguientes opciones:

  • Usar Generación Estática con obtención de datos en el lado del cliente: Puedes omitir el prerrenderizado de algunas partes de una página y luego usar JavaScript en el cliente para poblarlas. Para aprender más sobre este enfoque, consulta la documentación de Obtención de Datos.
  • Usar Renderizado del Lado del Servidor (SSR): Next.js prerrenderiza una página en cada solicitud. Será más lento porque la página no puede ser almacenada en caché por una CDN, pero la página prerrenderizada siempre estará actualizada. Hablaremos sobre este enfoque más adelante.

On this page