Exportación estática
Next.js permite comenzar como un sitio estático o una Aplicación de Página Única (SPA), y luego actualizar opcionalmente para usar funciones que requieran un servidor.
Al ejecutar next build
, Next.js genera un archivo HTML por ruta. Al dividir una SPA estricta en archivos HTML individuales, Next.js puede evitar cargar código JavaScript innecesario en el lado del cliente, reduciendo el tamaño del paquete y permitiendo cargas de página más rápidas.
Dado que Next.js admite esta exportación estática, puede implementarse y alojarse en cualquier servidor web que pueda servir recursos estáticos HTML/CSS/JS.
Configuración
Para habilitar una exportación estática, cambia el modo de salida en next.config.js
:
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
output: 'export',
// Opcional: Cambiar enlaces `/me` -> `/me/` y emitir `/me.html` -> `/me/index.html`
// trailingSlash: true,
// Opcional: Prevenir redirección automática `/me` -> `/me/`, preservando `href`
// skipTrailingSlashRedirect: true,
// Opcional: Cambiar directorio de salida `out` -> `dist`
// distDir: 'dist',
}
module.exports = nextConfig
Después de ejecutar next build
, Next.js producirá una carpeta out
que contiene los recursos HTML/CSS/JS para tu aplicación.
Funciones admitidas
El núcleo de Next.js ha sido diseñado para soportar exportaciones estáticas.
Componentes del servidor
Cuando ejecutas next build
para generar una exportación estática, los Componentes del Servidor consumidos dentro del directorio app
se ejecutarán durante la construcción, similar a la generación tradicional de sitios estáticos.
El componente resultante se renderizará en HTML estático para la carga inicial de la página y una carga útil estática para la navegación entre rutas en el cliente. No se requieren cambios para tus Componentes del Servidor al usar la exportación estática, a menos que consuman funciones dinámicas del servidor.
export default async function Page() {
// Esta solicitud se ejecutará en el servidor durante `next build`
const res = await fetch('https://api.example.com/...')
const data = await res.json()
return <main>...</main>
}
Componentes del cliente
Si deseas realizar obtención de datos en el cliente, puedes usar un Componente del Cliente con SWR para memorizar solicitudes.
'use client'
import useSWR from 'swr'
const fetcher = (url: string) => fetch(url).then((r) => r.json())
export default function Page() {
const { data, error } = useSWR(
`https://jsonplaceholder.typicode.com/posts/1`,
fetcher
)
if (error) return 'Error al cargar'
if (!data) return 'Cargando...'
return data.title
}
'use client'
import useSWR from 'swr'
const fetcher = (url) => fetch(url).then((r) => r.json())
export default function Page() {
const { data, error } = useSWR(
`https://jsonplaceholder.typicode.com/posts/1`,
fetcher
)
if (error) return 'Error al cargar'
if (!data) return 'Cargando...'
return data.title
}
Dado que las transiciones de ruta ocurren en el cliente, esto se comporta como una SPA tradicional. Por ejemplo, la siguiente ruta de índice te permite navegar a diferentes publicaciones en el cliente:
import Link from 'next/link'
export default function Page() {
return (
<>
<h1>Página de inicio</h1>
<hr />
<ul>
<li>
<Link href="/post/1">Publicación 1</Link>
</li>
<li>
<Link href="/post/2">Publicación 2</Link>
</li>
</ul>
</>
)
}
import Link from 'next/link'
export default function Page() {
return (
<>
<h1>Página de inicio</h1>
<p>
<Link href="/other">Otra página</Link>
</p>
</>
)
}
Optimización de imágenes
La Optimización de imágenes a través de next/image
puede usarse con una exportación estática definiendo un cargador personalizado en next.config.js
. Por ejemplo, puedes optimizar imágenes con un servicio como Cloudinary:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
images: {
loader: 'custom',
loaderFile: './my-loader.ts',
},
}
module.exports = nextConfig
Este cargador personalizado definirá cómo obtener imágenes desde una fuente remota. Por ejemplo, el siguiente cargador construirá la URL para Cloudinary:
export default function cloudinaryLoader({
src,
width,
quality,
}: {
src: string
width: number
quality?: number
}) {
const params = ['f_auto', 'c_limit', `w_${width}`, `q_${quality || 'auto'}`]
return `https://res.cloudinary.com/demo/image/upload/${params.join(
','
)}${src}`
}
export default function cloudinaryLoader({ src, width, quality }) {
const params = ['f_auto', 'c_limit', `w_${width}`, `q_${quality || 'auto'}`]
return `https://res.cloudinary.com/demo/image/upload/${params.join(
','
)}${src}`
}
Luego puedes usar next/image
en tu aplicación, definiendo rutas relativas a la imagen en Cloudinary:
import Image from 'next/image'
export default function Page() {
return <Image alt="tortugas" src="/turtles.jpg" width={300} height={300} />
}
import Image from 'next/image'
export default function Page() {
return <Image alt="tortugas" src="/turtles.jpg" width={300} height={300} />
}
Manejadores de ruta
Los Manejadores de Ruta renderizarán una respuesta estática al ejecutar next build
. Solo se admite el verbo HTTP GET
. Esto puede usarse para generar archivos estáticos HTML, JSON, TXT u otros desde datos cacheados o no cacheados. Por ejemplo:
export async function GET() {
return Response.json({ name: 'Lee' })
}
export async function GET() {
return Response.json({ name: 'Lee' })
}
El archivo anterior app/data.json/route.ts
se renderizará a un archivo estático durante next build
, produciendo data.json
que contiene { name: 'Lee' }
.
Si necesitas leer valores dinámicos de la solicitud entrante, no puedes usar una exportación estática.
APIs del navegador
Los Componentes del Cliente se prerrenderizan a HTML durante next build
. Dado que APIs web como window
, localStorage
y navigator
no están disponibles en el servidor, debes acceder a estas APIs de forma segura solo cuando se ejecutan en el navegador. Por ejemplo:
'use client';
import { useEffect } from 'react';
export default function ClientComponent() {
useEffect(() => {
// Ahora tienes acceso a `window`
console.log(window.innerHeight);
}, [])
return ...;
}
Funciones no admitidas
Las funciones que requieren un servidor Node.js, o lógica dinámica que no puede calcularse durante el proceso de construcción, no son compatibles:
- Rutas dinámicas con
dynamicParams: true
- Rutas dinámicas sin
generateStaticParams()
- Manejadores de ruta que dependen de Request
- Cookies
- Rewrites
- Redirects
- Headers
- Middleware
- Regeneración estática incremental
- Optimización de imágenes con el
loader
predeterminado - Modo borrador
Intentar usar cualquiera de estas funciones con next dev
resultará en un error, similar a establecer la opción dynamic
como error
en el diseño raíz.
export const dynamic = 'error'
Implementación
Con una exportación estática, Next.js puede implementarse y alojarse en cualquier servidor web que pueda servir recursos estáticos HTML/CSS/JS.
Al ejecutar next build
, Next.js genera la exportación estática en la carpeta out
. Por ejemplo, supongamos que tienes las siguientes rutas:
/
/blog/[id]
Después de ejecutar next build
, Next.js generará los siguientes archivos:
/out/index.html
/out/404.html
/out/blog/post-1.html
/out/blog/post-2.html
Si estás usando un host estático como Nginx, puedes configurar reescrituras desde solicitudes entrantes a los archivos correctos:
server {
listen 80;
server_name acme.com;
root /var/www/out;
location / {
try_files $uri $uri.html $uri/ =404;
}
# Esto es necesario cuando `trailingSlash: false`.
# Puedes omitirlo cuando `trailingSlash: true`.
location /blog/ {
rewrite ^/blog/(.*)$ /blog/$1.html break;
}
error_page 404 /404.html;
location = /404.html {
internal;
}
}
Historial de versiones
Versión | Cambios |
---|---|
v14.0.0 | next export ha sido eliminado en favor de "output": "export" |
v13.4.0 | Enrutador de Aplicaciones (Estable) agrega soporte mejorado para exportación estática, incluyendo Componentes del Servidor React y Manejadores de Ruta. |
v13.3.0 | next export está obsoleto y se reemplaza con "output": "export" |
Lista de verificación para producción
Recomendaciones para garantizar el mejor rendimiento y experiencia de usuario antes de llevar su aplicación Next.js a producción.
Multi-Zonas
Aprende a construir micro-frontends usando Multi-Zonas de Next.js para desplegar múltiples aplicaciones Next.js bajo un mismo dominio.