Introducción/Guías/Autoalojamiento

Cómo autoalojar tu aplicación Next.js

Al desplegar tu aplicación Next.js, es posible que desees configurar cómo se manejan las diferentes características según tu infraestructura.

🎥 Ver: Aprende más sobre autoalojar Next.js → YouTube (45 minutos).

Optimización de imágenes

La Optimización de imágenes a través de next/image funciona en autoalojamiento sin configuración cuando se despliega usando next start. Si prefieres tener un servicio separado para optimizar imágenes, puedes configurar un cargador de imágenes.

La Optimización de imágenes puede usarse con una exportación estática definiendo un cargador de imágenes personalizado en next.config.js. Ten en cuenta que las imágenes se optimizan en tiempo de ejecución, no durante la construcción.

Es bueno saber:

Middleware

El Middleware funciona en autoalojamiento sin configuración cuando se despliega usando next start. Como requiere acceso a la solicitud entrante, no es compatible cuando se usa una exportación estática.

El Middleware utiliza el entorno de ejecución Edge, un subconjunto de todas las API de Node.js disponibles para ayudar a garantizar baja latencia, ya que puede ejecutarse antes de cada ruta o recurso en tu aplicación. Si no deseas esto, puedes usar el entorno de ejecución completo de Node.js para ejecutar Middleware.

Si deseas agregar lógica (o usar un paquete externo) que requiera todas las API de Node.js, podrías mover esta lógica a un layout como un Componente de Servidor. Por ejemplo, verificar encabezados y redireccionar. También puedes usar encabezados, cookies o parámetros de consulta para redireccionar o reescribir a través de next.config.js. Si eso no funciona, también puedes usar un servidor personalizado.

Variables de entorno

Next.js puede soportar variables de entorno tanto en tiempo de construcción como en tiempo de ejecución.

Por defecto, las variables de entorno solo están disponibles en el servidor. Para exponer una variable de entorno al navegador, debe tener el prefijo NEXT_PUBLIC_. Sin embargo, estas variables de entorno públicas se incluirán en el paquete JavaScript durante next build.

Puedes leer variables de entorno de forma segura en el servidor durante el renderizado dinámico.

import { connection } from 'next/server'

export default async function Component() {
  await connection()
  // cookies, headers y otras API dinámicas
  // también optarán por el renderizado dinámico, lo que significa
  // que esta variable de entorno se evalúa en tiempo de ejecución
  const value = process.env.MY_VALUE
  // ...
}

Esto te permite usar una única imagen Docker que puede promoverse a través de múltiples entornos con diferentes valores.

Es bueno saber:

Caché e ISR

Next.js puede almacenar en caché respuestas, páginas estáticas generadas, salidas de construcción y otros recursos estáticos como imágenes, fuentes y scripts.

El almacenamiento en caché y la revalidación de páginas (con Regeneración Estática Incremental) usan la misma caché compartida. Por defecto, esta caché se almacena en el sistema de archivos (en disco) en tu servidor Next.js. Esto funciona automáticamente en autoalojamiento usando tanto el Enrutador de Páginas como el de Aplicación.

Puedes configurar la ubicación de la caché de Next.js si deseas persistir páginas y datos en caché en almacenamiento duradero, o compartir la caché entre múltiples contenedores o instancias de tu aplicación Next.js.

Caché automática

  • Next.js establece el encabezado Cache-Control en public, max-age=31536000, immutable para recursos verdaderamente inmutables. No se puede anular. Estos archivos inmutables contienen un hash SHA en el nombre del archivo, por lo que pueden almacenarse en caché indefinidamente. Por ejemplo, Importaciones de imágenes estáticas. Puedes configurar el TTL para imágenes.
  • La Regeneración Estática Incremental (ISR) establece el encabezado Cache-Control en s-maxage: <revalidate in getStaticProps>, stale-while-revalidate. Este tiempo de revalidación se define en tu función getStaticProps en segundos. Si estableces revalidate: false, se establecerá por defecto en una duración de caché de un año.
  • Las páginas renderizadas dinámicamente establecen un encabezado Cache-Control de private, no-cache, no-store, max-age=0, must-revalidate para evitar que los datos específicos del usuario se almacenen en caché. Esto se aplica tanto al Enrutador de Aplicación como al de Páginas. Esto también incluye el Modo Borrador.

Recursos estáticos

Si deseas alojar recursos estáticos en un dominio o CDN diferente, puedes usar la configuración assetPrefix en next.config.js. Next.js usará este prefijo de recurso al recuperar archivos JavaScript o CSS. Separar tus recursos a un dominio diferente tiene la desventaja de un tiempo adicional dedicado a la resolución de DNS y TLS.

Aprende más sobre assetPrefix.

Configuración de la caché

Por defecto, los recursos de caché generados se almacenarán en memoria (por defecto 50mb) y en disco. Si estás alojando Next.js usando una plataforma de orquestación de contenedores como Kubernetes, cada pod tendrá una copia de la caché. Para evitar que se muestren datos obsoletos ya que la caché no se comparte entre pods por defecto, puedes configurar la caché de Next.js para proporcionar un manejador de caché y desactivar el almacenamiento en caché en memoria.

Para configurar la ubicación de la caché ISR/Data cuando se autoaloja, puedes configurar un manejador personalizado en tu archivo next.config.js:

next.config.js
module.exports = {
  cacheHandler: require.resolve('./cache-handler.js'),
  cacheMaxMemorySize: 0, // desactivar el almacenamiento en caché en memoria por defecto
}

Luego, crea cache-handler.js en la raíz de tu proyecto, por ejemplo:

cache-handler.js
const cache = new Map()

module.exports = class CacheHandler {
  constructor(options) {
    this.options = options
  }

  async get(key) {
    // Esto podría almacenarse en cualquier lugar, como almacenamiento duradero
    return cache.get(key)
  }

  async set(key, data, ctx) {
    // Esto podría almacenarse en cualquier lugar, como almacenamiento duradero
    cache.set(key, {
      value: data,
      lastModified: Date.now(),
      tags: ctx.tags,
    })
  }

  async revalidateTag(tags) {
    // tags es una cadena o un array de cadenas
    tags = [tags].flat()
    // Iterar sobre todas las entradas en la caché
    for (let [key, value] of cache) {
      // Si las etiquetas del valor incluyen la etiqueta especificada, eliminar esta entrada
      if (value.tags.some((tag) => tags.includes(tag))) {
        cache.delete(key)
      }
    }
  }

  // Si deseas tener una caché temporal en memoria para una sola solicitud que se reinicia
  // antes de la siguiente solicitud, puedes aprovechar este método
  resetRequestCache() {}
}

Usar un manejador de caché personalizado te permitirá garantizar la consistencia en todos los pods que alojan tu aplicación Next.js. Por ejemplo, puedes guardar los valores en caché en cualquier lugar, como Redis o AWS S3.

Es bueno saber:

  • revalidatePath es una capa de conveniencia sobre las etiquetas de caché. Llamar a revalidatePath llamará a la función revalidateTag con una etiqueta predeterminada especial para la página proporcionada.

Caché de construcción

Next.js genera un ID durante next build para identificar qué versión de tu aplicación se está sirviendo. La misma construcción debe usarse e iniciarse en múltiples contenedores.

Si estás reconstruyendo para cada etapa de tu entorno, necesitarás generar un ID de construcción consistente para usar entre contenedores. Usa el comando generateBuildId en next.config.js:

next.config.js
module.exports = {
  generateBuildId: async () => {
    // Esto podría ser cualquier cosa, usando el último hash de git
    return process.env.GIT_HASH
  },
}

Desfase de versión

Next.js mitigará automáticamente la mayoría de los casos de desfase de versión y recargará automáticamente la aplicación para recuperar nuevos recursos cuando se detecte. Por ejemplo, si hay una discrepancia en el deploymentId, las transiciones entre páginas realizarán una navegación dura en lugar de usar un valor precargado.

Cuando la aplicación se recarga, puede haber una pérdida del estado de la aplicación si no está diseñada para persistir entre navegaciones de página. Por ejemplo, usar el estado de la URL o el almacenamiento local persistiría el estado después de una actualización de página. Sin embargo, el estado del componente como useState se perdería en tales navegaciones.

Streaming y Suspense

El Enrutador de Aplicación de Next.js soporta respuestas en streaming en autoalojamiento. Si estás usando Nginx o un proxy similar, necesitarás configurarlo para desactivar el buffering y habilitar el streaming.

Por ejemplo, puedes desactivar el buffering en Nginx estableciendo X-Accel-Buffering en no:

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*{/}?',
        headers: [
          {
            key: 'X-Accel-Buffering',
            value: 'no',
          },
        ],
      },
    ]
  },
}

Prerenderizado parcial

El Prerenderizado parcial (experimental) funciona por defecto con Next.js y no es una función exclusiva de CDN. Esto incluye el despliegue como un servidor Node.js (a través de next start) y cuando se usa con un contenedor Docker.

Uso con CDNs

Cuando usas un CDN delante de tu aplicación Next.js, la página incluirá el encabezado de respuesta Cache-Control: private cuando se accede a API dinámicas. Esto asegura que la página HTML resultante se marque como no almacenable en caché. Si la página está completamente prerenderizada a estático, incluirá Cache-Control: public para permitir que la página se almacene en caché en el CDN.

Si no necesitas una mezcla de componentes estáticos y dinámicos, puedes hacer que toda tu ruta sea estática y almacenar en caché el HTML de salida en un CDN. Esta Optimización Estática Automática es el comportamiento predeterminado cuando ejecutas next build si no se usan API dinámicas.

A medida que el Prerenderizado parcial se estabilice, proporcionaremos soporte a través de la API de Adaptadores de Despliegue.

after

after es totalmente compatible cuando se autoaloja con next start.

Al detener el servidor, asegura un apagado elegante enviando señales SIGINT o SIGTERM y esperando. Esto permite que el servidor Next.js espere hasta que las funciones de callback pendientes o promesas usadas dentro de after hayan terminado.

On this page