BackVolver al blog

Next.js 9.5

Next.js 9.5 introduce Regeneración Estática Incremental estable, Ruta Base Personalizable, Redirecciones y Reescribir URLs, Webpack 5 Beta, ¡y más!

Hoy estamos emocionados de presentar Next.js 9.5, que incluye:

Regeneración Estática Incremental estable

Next.js introdujo métodos de Generación de Sitios Estáticos en la versión 9.3 con un objetivo claro: obtener los beneficios de lo estático (siempre rápido, siempre en línea, replicado globalmente), pero con excelente soporte para datos dinámicos, por lo que Next.js es conocido.

Para obtener lo mejor de ambos mundos, Next.js introdujo la Generación Estática Incremental, actualizando contenido estático después de haber construido tu sitio. Usando la opción fallback: true en getStaticPaths, puedes registrar nuevas páginas estáticas en tiempo de ejecución.

Next.js puede pre-renderizar estáticamente un número infinito de páginas de esta manera, bajo demanda, sin importar el tamaño de tu conjunto de datos.

Hoy, anunciamos la disponibilidad general de la Regeneración Estática Incremental, un mecanismo para actualizar páginas existentes, re-renderizándolas en segundo plano según llega tráfico.

Inspirado por stale-while-revalidate, la regeneración en segundo plano asegura que el tráfico se sirva sin interrupciones, siempre desde almacenamiento estático, y la nueva página construida se envía solo después de completar su generación.

export async function getStaticProps() {
  return {
    props: await getDataFromCMS(),
    // intentaremos regenerar la página:
    // - cuando llegue una solicitud
    // - como máximo una vez por segundo
    revalidate: 1,
  };
}

La bandera revalidate es el número de segundos durante los cuales ocurrirá como máximo una regeneración, para prevenir un https://en.wikipedia.org/wiki/Cache_stampede.

A diferencia del SSR tradicional, la Regeneración Estática Incremental asegura que conserves los beneficios de lo estático:

  • Sin picos de latencia. Las páginas se sirven consistentemente rápido.
  • Las páginas nunca se caen. Si falla la regeneración en segundo plano, la página antigua permanece sin cambios.
  • Baja carga en base de datos y backend. Las páginas se recomputan como máximo una vez concurrentemente.

Ambas características incrementales (añadir páginas y actualizarlas perezosamente), así como el modo de vista previa, ahora son estables y están completamente soportadas tanto por next start como por la plataforma edge de Vercel sin configuración adicional.

Para mostrar esta nueva característica, hemos creado un ejemplo que muestra la regeneración de una página estática con el conteo de reacciones GitHub de un issue específico: https://reactions-demo.vercel.app/

Después de la primera visita siguiendo nuestra reacción con emoji, una nueva generación de página comienza en segundo plano. Cada solicitud se sirve desde caché estático.

Después de la primera visita siguiendo nuestra reacción con emoji, una nueva generación de página comienza en segundo plano. Cada solicitud se sirve desde caché estático.

Próximamente, trabajaremos en un RFC complementario para abordar dos capacidades adicionales de generación estática incremental:

  • Regenerar e invalidar múltiples páginas a la vez (como tu índice de blog y una entrada específica)
  • Regenerar escuchando eventos (como webhooks de CMS), antes del tráfico de usuarios

Para más detalles, consulta la documentación de getStaticProps.

Ruta Base Personalizable

Los proyectos Next.js no siempre se sirven desde la raíz de un dominio. A veces puedes querer alojar tu proyecto Next.js bajo una subruta como /docs para que el proyecto Next.js solo cubra esa sección del dominio.

Aunque esto ha sido posible hasta ahora, requería bastante configuración adicional. Por ejemplo, añadir el prefijo a cada <Link> y asegurarse de que Next.js sirviera los paquetes JavaScript desde la ruta correcta.

Para abordar este problema, introducimos una nueva opción de configuración. basePath te permite alojar fácilmente tu proyecto Next.js en una subruta de tu dominio.

Para comenzar a usar basePath puedes añadirlo a next.config.js:

next.config.js
module.exports = {
  basePath: '/docs',
};

Después de configurar basePath, tu proyecto se enrutará automáticamente desde la ruta proporcionada. En este caso, /docs.

Al enlazar a otras páginas del proyecto con next/link o next/router, el basePath se prefijará automáticamente. Esto te permite cambiar el basePath sin modificar tu proyecto.

Un ejemplo sería usar next/link para enrutar a otra página:

import Link from 'next/link';
 
export default function HomePage() {
  return (
    <>
      <Link href="/documentation-page">
        <a>Página de documentación</a>
      </Link>
    </>
  );
}

Usar next/link de esta manera generará el siguiente HTML en el navegador:

<a href="/docs/documentation-page">Página de documentación</a>

Para más detalles, consulta la documentación de basePath.

Soporte para Reescribir URLs, Redirecciones y Cabeceras

Reescribir URLs

Al construir un proyecto Next.js puedes querer redirigir ciertas rutas a otra URL. Por ejemplo, si quieres adoptar Next.js incrementalmente en tu stack, podrías enrutar páginas que existen en tu proyecto Next.js y luego redirigir lo no coincidente al proyecto antiguo que estás migrando.

Con Next.js 9.5 introducimos una nueva opción de configuración llamada rewrites, que te permite mapear una ruta de solicitud entrante a un destino diferente, incluyendo URLs externas.

Por ejemplo, podrías querer reescribir cierta ruta a example.com:

next.config.js
module.exports = {
  async rewrites() {
    return [
      { source: '/backend/:path*', destination: 'https://example.com/:path*' },
    ];
  },
};

En este caso, todas las rutas bajo /backend se enrutarían a example.com.

También puedes verificar si las rutas de tu proyecto Next.js coinciden y luego reescribir al proyecto anterior si no hay coincidencia. Esto es increíblemente útil para la adopción incremental de Next.js:

module.exports = {
  async rewrites() {
    return [
      // verificar si coinciden las rutas del proyecto Next.js antes de intentar proxy
      {
        source: '/:path*',
        destination: '/:path*',
      },
      {
        source: '/:path*',
        destination: `https://example.com/:path*`,
      },
    ];
  },
};

En este caso, primero coincidimos todas las rutas. Si ninguna coincide, hacemos proxy a example.com, que sería el proyecto anterior.

Para aprender más sobre la característica rewrites, consulta la documentación de reescrituras.

Redirecciones

La mayoría de sitios web necesitan al menos algunas redirecciones. Especialmente al cambiar la estructura de las rutas de tu proyecto. Por ejemplo, al mover /blog a /news o transiciones similares.

Anteriormente, tener una lista de redirecciones en tu proyecto Next.js requería configurar un servidor personalizado o una página _error personalizada para verificar si había redirecciones para la ruta. Sin embargo, esto invalidaba optimizaciones clave estáticas y serverless (al tener un servidor) o no era lo suficientemente ergonómico.

A partir de Next.js 9.5 puedes crear una lista de redirecciones en next.config.js bajo la clave redirects:

next.config.js
module.exports = {
  async redirects() {
    return [
      {
        source: '/about',
        destination: '/',
        permanent: true,
      },
    ];
  },
};

Para aprender más sobre la característica redirects, consulta la documentación de redirecciones.

Encabezados (Headers)

Next.js le permite construir proyectos híbridos que utilizan tanto Generación Estática como Renderizado del Lado del Servidor (SSR). Con el Renderizado del Lado del Servidor, puede establecer encabezados para la solicitud entrante. Para páginas estáticas, establecer encabezados no era posible hasta ahora.

Hemos introducido una propiedad headers en next.config.js que se aplica a todas las rutas de Next.js:

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Feature-Policy',
            // Deshabilitar micrófono y geolocalización
            value: "microphone 'none'; geolocation 'none'",
          },
        ],
      },
    ];
  },
};

La opción headers le permite establecer encabezados comúnmente necesarios como Feature-Policy y Content-Security-Policy.

Para obtener más información sobre la función headers, consulte la documentación de headers.

Barra diagonal opcional en URLs (Optional Trailing Slash in URLs)

Cuando Next.js se introdujo hace 3 años, su comportamiento predeterminado era que todas las URLs con una barra diagonal final siempre devolvieran una página 404.

Aunque efectivo, algunos usuarios solicitaron la capacidad de cambiar este comportamiento. Por ejemplo, al migrar un proyecto existente a Next.js que anteriormente siempre tenía barras diagonales finales forzadas.

Con Next.js 9.5 hemos introducido una nueva opción llamada trailingSlash en next.config.js.

Esta nueva opción asegura que Next.js maneje automáticamente el comportamiento de la barra diagonal final:

  • Redirige automáticamente las URLs con barra diagonal final a la URL sin la barra diagonal, por ejemplo: /about/ a /about
  • Cuando trailingSlash se establece en true, la URL sin barra diagonal final será redirigida a la URL con barra diagonal, por ejemplo: /about a /about/
  • Asegura que next/link aplique/elimine automáticamente la barra diagonal final para evitar redirecciones innecesarias.
next.config.js
module.exports = {
  // Forzar una barra diagonal final, el valor predeterminado es sin barra diagonal final (false)
  trailingSlash: true,
};

Para obtener más información sobre la función trailingSlash, consulte la documentación de trailingSlash

Almacenamiento en caché persistente para paquetes de página (Persistent Caching for Page Bundles)

Al escribir páginas en Next.js, la creación de todos los paquetes de scripts, hojas de estilo CSS y HTML es completamente automática y abstracta para usted. Si inspecciona las etiquetas <script> generadas antes de Next.js 9.5, notará que sus URLs siguen un patrón como este:

/_next/static/ovgxWYrvKyjnlM15qtz7h/pages/about.js

El segmento de ruta ovgxWYrvKyjnlM15qtz7h anterior es lo que llamamos el ID de compilación. Aunque estos archivos eran fácilmente almacenables en caché en el edge y en la máquina del usuario, después de recompilar su aplicación, el ID de compilación cambiaría y todas las cachés se invalidarían.

Para la mayoría de los proyectos, esta compensación era aceptable, sin embargo, queríamos optimizar aún más este comportamiento al no invalidar más la caché del navegador para páginas que no habían cambiado.

La introducción de la estrategia mejorada de división de código en Next.js 9.2, desarrollada en colaboración con el equipo de Google Chrome, sentó las bases para estas mejoras en la generación de paquetes de página de Next.js.

A partir de Next.js 9.5, todos los paquetes JavaScript de página utilizarán hashes de contenido en lugar del ID de compilación. Esto permite que las páginas que no han cambiado entre despliegues permanezcan en la caché del navegador y del edge sin necesidad de volver a descargarse.

En contraste, el patrón de URL después de estos cambios se ve así:

/_next/static/chunks/pages/about.qzfS4o5gIEXRME6sTEahL.js```

En lugar de un ID de compilación global, la parte `qzfS4o5gIEXRME6sTEahL` es un hash determinista del paquete `about.js`, que será estable siempre que el código de esa sección de su sitio no cambie. Además, **ahora se almacena en caché a largo plazo entre re-despliegues** mediante `Cache-Control: public,max-age=31536000,immutable`, que Next.js establece automáticamente para usted.

[Mejoras en Fast Refresh](#fast-refresh-enhancements)
-----------------------------------------------------

Presentamos [Fast Refresh en Next.js 9.4](https://nextjs.org/blog/next-9-4#fast-refresh), una nueva experiencia de recarga en caliente que le brinda retroalimentación instantánea sobre los cambios realizados en sus componentes React.

Next.js 9.5 refina aún más nuestra implementación de Fast Refresh y le brinda las herramientas que necesita para tener éxito:

*   **Errores fáciles de entender**: Todos los errores de compilación y tiempo de ejecución se actualizaron para [mostrar solo información relevante, incluido un marco de código del código que causó el error](https://twitter.com/timer150/status/1263689549898829829).
*   **Consejos para mantener el estado del componente**: Next.js ahora le proporciona consejos útiles para garantizar que Fast Refresh mantenga el estado de su componente en la mayor cantidad de escenarios posible. ¡Cada consejo que Next.js proporciona es **totalmente accionable** y viene acompañado de un ejemplo antes y después!
*   **Advertencias cuando se restablece el estado del componente**: Ahora imprimiremos una advertencia detallada cuando Next.js no pueda mantener el estado del componente después de editar un archivo. Esta advertencia le ayudará a diagnosticar por qué el proyecto tuvo que restablecer el estado del componente, permitiéndole solucionarlo y utilizar Fast Refresh a su máximo potencial.
*   **Nueva documentación**: Hemos [agregado documentación extensa](/docs/architecture/fast-refresh) que explica qué es Fast Refresh, cómo funciona y qué esperar. La documentación también le enseñará cómo aprovechar mejor Fast Refresh al explicar cómo funciona su recuperación de errores.
*   **Guía de solución de problemas para código de usuario**: La nueva documentación también incluye [pasos comunes de solución de problemas y consejos](/docs/architecture/fast-refresh#tips) sobre cómo aprovechar al máximo Fast Refresh en desarrollo.

[Perfilado de React en producción (Production React Profiling)](#production-react-profiling)
---------------------------------------------------------

React introdujo la [API de Profiler](https://github.com/reactjs/rfcs/pull/51) hace un tiempo, que le permite rastrear problemas de rendimiento en sus componentes React. Si bien esta función funciona automáticamente en desarrollo, requiere una versión separada de ReactDOM para perfilar en producción.

Con Next.js 9.5, ahora puede **habilitar el perfilado de producción para React** con la bandera `--profile` en `next build`:

next build --profile


Después de eso, puede usar el perfilador de la misma manera que lo haría en desarrollo.

Para obtener más información sobre el perfilado de React, puede leer [la publicación sobre el Profiler de React por el equipo de React](https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html). Un agradecimiento especial a [TODOrTotev](https://github.com/TodorTotev) y [@darshkpatel](https://github.com/darshkpatel) por contribuir con esta función.

[Rutas de captura opcional (Optional Catch All Routes)](#optional-catch-all-routes)
-----------------------------------------------------

Next.js 9.2 agregó [soporte para rutas dinámicas de captura total](https://nextjs.org/blog/next-9-2#catch-all-dynamic-routes), que han sido ampliamente adoptadas por la comunidad para diversos casos de uso. Las rutas de captura total le brindan la flexibilidad de crear estructuras de enrutamiento altamente dinámicas impulsadas por CMS sin cabeza, APIs GraphQL, sistema de archivos, etc.

Al escuchar los comentarios, los usuarios expresaron que querían tener aún más flexibilidad para _coincidir con el nivel más alto de una ruta_. Hoy, nos complace presentar **rutas dinámicas de captura total opcionales** para estos escenarios avanzados.

Para crear una ruta de captura total opcional, puede crear una página usando la sintaxis `[[...slug]]`.

Por ejemplo, `pages/blog/[[...slug]].js` coincidirá con `/blog`, así como con cualquier ruta debajo de ella, como: `/blog/a`, `/blog/a/b/c`, y así sucesivamente.

Al igual que las rutas de captura total, `slug` se proporcionará en el [objeto de consulta del enrutador](/docs/pages/api-reference/functions/use-router#router-object) como un array de partes de la ruta. Entonces, para la ruta `/blog/foo/bar`, el objeto de consulta será `{ slug: ['foo', 'bar'] }`. Para la ruta `/blog`, el objeto de consulta omitirá la clave slug: `{ }`.

Puede [aprender más sobre las rutas de captura total opcional en nuestra documentación](/docs/pages/building-your-application/routing/dynamic-routes#optional-catch-all-routes).

[Soporte para Webpack 5 (beta)](#webpack-5-support-beta)
---------------------------------------------------

Webpack 5 está actualmente en beta. Incluye algunas mejoras importantes:

*   [Mejor Tree-Shaking](https://github.com/webpack/changelog-v5#nested-tree-shaking): Las exportaciones anidadas, módulos internos y CommonJS se optimizan mejor.
*   [Almacenamiento en caché persistente](https://github.com/webpack/changelog-v5#persistent-caching): Permite reutilizar el trabajo de compilaciones anteriores.
*   [IDs de módulo y chunk determinísticos](https://github.com/webpack/changelog-v5#deterministic-chunk-and-module-ids): Resuelve casos donde los IDs de módulo de webpack cambiarían entre compilaciones.

Nos complace anunciar hoy la disponibilidad beta de webpack 5 para Next.js.

Para probar webpack 5, puede usar [Yarn resolutions](https://classic.yarnpkg.com/en/docs/selective-version-resolutions/) en su `package.json`:

```json filename="package.json"
{
  "resolutions": {
    "webpack": "^5.0.0-beta.30"
  }
}

La beta de Webpack 5 ya se ha implementado en producción en nextjs.org y vercel.com. Le animamos a probarla de manera progresiva y compartir sus hallazgos en GitHub.

Mejoras en la infraestructura de compilación

Para admitir webpack 5, hemos reescrito gran parte de la canalización de compilación para adaptarse mejor a Next.js:

  • Next.js ya no depende de webpack-hot-middleware y webpack-dev-middleware, en su lugar ahora usamos webpack directamente y optimizamos específicamente para proyectos Next.js. Esto se traduce en una arquitectura más simple y una compilación de desarrollo más rápida.
  • On-demand-entries, que es el sistema que Next.js tiene para permitirle compilar las páginas que visita en un momento dado durante el desarrollo, también se ha reescrito y ahora es aún más confiable al aprovechar el nuevo comportamiento de webpack específicamente adaptado para nuestro caso de uso.
  • React Fast Refresh y el Next.js Error Overlay ahora son totalmente compatibles con webpack 5.
  • El almacenamiento en caché en disco se habilitará en una futura versión beta.

Compatibilidad con versiones anteriores

Siempre nos comprometemos a garantizar que Next.js sea compatible con versiones anteriores.

Webpack 4 seguirá siendo totalmente compatible. Estamos trabajando estrechamente con el equipo de webpack para garantizar que la migración de webpack 4 a 5 sea lo más fluida posible.

Si su proyecto Next.js no tiene configuración personalizada de webpack, no se necesitarán cambios en el proyecto para aprovechar completamente webpack 5.

Importante: si su proyecto tiene configuración personalizada de webpack, es posible que se necesiten algunos cambios para la transición a webpack 5. Recomendamos estar atento a nuestras instrucciones de migración o minimizar el uso de extensiones de webpack para futuras actualizaciones sin problemas.

Mejora en la observación de archivos en macOS

Recientemente encontramos un problema con webpack donde la observación de archivos en macOS se detenía después de realizar algunos cambios en su código. Tendría que reiniciar su proyecto manualmente para ver las actualizaciones nuevamente. Después de algunos cambios, el ciclo se repetiría.

Además, descubrimos que este problema no solo ocurría en proyectos Next.js, sino en todos los proyectos y frameworks que se construyen sobre webpack.

Después de varios días de depuración, rastreamos la causa raíz a la implementación de observación de archivos que webpack usa llamada chokidar, que es una implementación de observación de archivos ampliamente utilizada en el ecosistema de Node.js.

Enviamos un parche a chokidar para solucionar el problema. Después de que se lanzó el parche, trabajamos con Tobias Koppers para implementar este parche en una nueva versión de webpack.

Esta versión parcheada de webpack se usa automáticamente cuando actualiza a Next.js 9.5.

Conclusión

Nos entusiasma ver el crecimiento continuo en la adopción de Next.js:

  • Hemos tenido más de 1,200 colaboradores independientes, con más de 135 nuevos colaboradores desde el lanzamiento de la versión 9.4.
  • En GitHub, el proyecto ha recibido más de 51,100 estrellas.

Únase a la comunidad de Next.js en GitHub Discussions. Discussions es un espacio comunitario que le permite conectarse con otros usuarios de Next.js y hacer preguntas o compartir su trabajo libremente.

Por ejemplo, puede comenzar compartiendo la URL de su proyecto con todos.

Si desea contribuir pero no está seguro de cómo hacerlo, ¡le animamos a probar funciones experimentales como nuestro soporte para Webpack y compartir sus hallazgos!

Créditos

Estamos agradecidos con nuestra comunidad, incluyendo todos los comentarios externos y contribuciones que ayudaron a dar forma a este lanzamiento.

Un agradecimiento especial a Jan Potoms, un miembro de la comunidad de Next.js desde hace mucho tiempo que contribuyó a múltiples funciones en este lanzamiento.

Un agradecimiento especial a Tobias Koppers, el autor de webpack, quien ayudó a implementar el soporte de webpack 5 en Next.js.

Este lanzamiento fue posible gracias a las contribuciones de: @chandan-reddy-k, @Timer, @aralroca, @artemisart, @sospedra, @prateekbh, @Prioe, @Janpot, @merceyz, @ijjk, @PavelK27, @marbiano, @MichelleLucero, @thorsten-stripe, @TODOrTotev, @Skn0tt, @lfades, @timneutkens, @akhila-ariyachandra, @chibicode, @rafaelalmeidatk, @kirill-konshin, @jamesvidler, @JeffersonBledsoe, @tylev, @jamesmosier, @filipemarins, @Remeic, @vvo, @timothyis, @jazibsawar, @coetry, @adam-zacharski, @danwilliams, @tywmick, @matamatanot, @goldins, @mvllow, @its-tayo, @sshyam-gupta, @wilbert-abreu, @sebastianbenz, @jaydenseric, @developit, @dylanjha, @darshkpatel, @spinks, @stefanprobst, @moh12594, @jasonmerino, @cristiand391, @HyunSangHan, @mcsdevv, @M1ck0, @hydRAnger, @alexej-d, @valmassoi, @motleydev, @eKhattak, @jpedroschmitz, @JerryGoyal, @bowen31337, @phillip055, @balazsorban44, @chuabingquan, @youhosi, @andresz1, @bell-steven, @areai51, @Wssn, @ndom91, @anthonyshort, @zxzl, @jbowes, @IamLizu, @PascalPixel, @ralphilius, @ysun62, @muslax, @elsigh, @AsherFoster, @botv, @tomdohnal, @christianalfoni, @tomasztunik, @gsimone, @illuminist, @jplew, @OskarKaminski, @RickyAbell, @steph-query, @ericgoe, @MalvinJay, @cristianbote, @Ashikpaul, @jensmeindertsma, @amorriscode, @abhik-b, @awareness481, @LukasPolak, @arvigeus, @romMidnight, @jackyef, @drumm2k, @kuldeepkeshwar, @bogy0, @Belco90, @wawjr3d, @tanmaylaud, @SarKurd, @kevinsproles, @dstotijn, @styfle, @blackwright, @BrunoBernardino, @heyAyushh, @Necmttn, @TrySound, @obedparla, @NyashaNziramasanga, @tonyspiro, @kukicado, @ceorourke, @MehediH, @robintom, @karlhorky, y @tcK1!