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.

Para leer variables de entorno en tiempo de ejecución, recomendamos usar getServerSideProps o adoptar incrementalmente el Enrutador de Aplicación.

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.

Apagados elegantes manuales

Cuando autoalojas, es posible que desees ejecutar código cuando el servidor se apaga con señales SIGTERM o SIGINT.

Puedes establecer la variable de entorno NEXT_MANUAL_SIG_HANDLE en true y luego registrar un manejador para esa señal dentro de tu archivo _document.js. Necesitarás registrar la variable de entorno directamente en el script package.json, y no en el archivo .env.

Es bueno saber: El manejo manual de señales no está disponible en next dev.

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "NEXT_MANUAL_SIG_HANDLE=true next start"
  }
}
pages/_document.js
if (process.env.NEXT_MANUAL_SIG_HANDLE) {
  process.on('SIGTERM', () => {
    console.log('Recibido SIGTERM: limpiando')
    process.exit(0)
  })
  process.on('SIGINT', () => {
    console.log('Recibido SIGINT: limpiando')
    process.exit(0)
  })
}

On this page