BackVolver al blog

Next.js 9.2

Next.js 9.2 introduce soporte nativo para CSS, división agresiva de código (code-splitting), rutas dinámicas catch-all, ¡y mucho más!

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

Todos estos beneficios son no disruptivos y completamente compatibles con versiones anteriores. Para actualizar, solo necesita ejecutar:

Terminal
npm i next@latest react@latest react-dom@latest

Soporte incorporado para CSS en hojas de estilo globales

Next.js 5 introdujo soporte para importar CSS a través de un plugin personalizado llamado next-css que extendía el comportamiento de Next.js.

Con el tiempo recibimos comentarios consistentes de empresas y usuarios de Next.js, mencionando que frecuentemente terminaban agregando next-css a sus aplicaciones.

Además, next-css tenía algunas limitaciones al importar CSS. Por ejemplo, podías importar un archivo CSS en cada archivo del proyecto, pero este archivo CSS importado sería global para toda la aplicación.

Para mejorar la experiencia del desarrollador y resolver estas inconsistencias, comenzamos a trabajar en integrar el soporte para importar CSS en Next.js por defecto.

Nos complace anunciar que Next.js ahora tiene soporte nativo para importar hojas de estilo en su aplicación.

Para comenzar a usar importaciones CSS en su aplicación, importe el archivo CSS dentro de pages/_app.js.

Por ejemplo, considere la siguiente hoja de estilo llamada styles.css en la raíz de su proyecto:

body {
  padding: 20px 20px 60px;
  margin: 0;
}

Cree un archivo pages/_app.js si aún no está presente.

Luego, importe el archivo styles.css:

pages/_app.js
import '../styles.css';
 
// Esta exportación por defecto es requerida en un nuevo archivo `pages/_app.js`.
export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

Dado que las hojas de estilo son globales por naturaleza, deben importarse en el componente <App> personalizado. Esto es necesario para evitar conflictos de nombres de clases y orden en estilos globales.

En desarrollo, expresar hojas de estilo de esta manera permite que tus estilos se actualicen automáticamente en la página mientras los editas.

En producción, todos los archivos CSS se concatenarán automáticamente en un único archivo .css minificado. Este archivo CSS se cargará mediante una etiqueta <link> y se inyectará automáticamente en el marcado HTML predeterminado que genera Next.js.

Esta nueva característica es completamente compatible con versiones anteriores. Si está utilizando @zeit/next-css u otros plugins relacionados con CSS, la característica se desactiva para evitar conflictos.

Si actualmente usa @zeit/next-css, le recomendamos eliminar el plugin de su next.config.js y package.json, migrando así al soporte incorporado para CSS al actualizar.

Soporte incorporado para módulos CSS en estilos a nivel de componente

Next.js ahora soporta Módulos CSS usando la convención de nombres de archivo [name].module.css.

A diferencia del soporte disponible anteriormente en Next.js 5 usando next-css, ahora el CSS global y los módulos CSS pueden coexistirnext-css requería que todos los archivos .css en su aplicación se manejaran como globales o locales, pero no ambos.

Los Módulos CSS limitan el alcance del CSS localmente al crear automáticamente nombres de clases únicos. Esto te permite usar el mismo nombre de clase CSS en diferentes archivos sin preocuparte por colisiones.

Este comportamiento hace que los Módulos CSS sean la forma ideal de incluir CSS a nivel de componente. Los archivos de Módulos CSS pueden importarse en cualquier parte de tu aplicación.

Por ejemplo, considere un componente reutilizable Button en la carpeta components/:

Primero, cree components/Button.module.css con el siguiente contenido:

/*
No necesita preocuparse por que .error {} colisione con otros archivos `.css` o
`.module.css`!
*/
.error {
  color: white;
  background-color: red;
}

Luego, cree components/Button.js, importando y usando el archivo CSS anterior:

components/Button.js
import styles from './Button.module.css';
 
export function Button() {
  return (
    <button
      type="button"
      // Observe cómo la clase "error" se accede como una propiedad en el objeto
      // `styles` importado.
      className={styles.error}
    >
      Destroy
    </button>
  );
}

Los Módulos CSS son una característica opcional y solo se activan para archivos con la extensión .module.css. Todavía se admiten las hojas de estilo <link> regulares y archivos CSS globales.

En producción, todos los archivos de Módulos CSS se concatenan automáticamente en muchos archivos .css minificados y divididos por código (code-split). Estos archivos .css representan rutas de ejecución críticas en su aplicación, garantizando que se cargue la cantidad mínima de CSS por página para que su aplicación se renderice.

Como se mencionó anteriormente, esta nueva característica es completamente compatible con versiones anteriores. Si está utilizando @zeit/next-css u otros plugins relacionados con CSS, la característica se desactiva para evitar conflictos.

Si actualmente usa @zeit/next-css, le recomendamos eliminar el plugin de su next.config.js y package.json, migrando así al soporte incorporado para CSS.

Estrategia mejorada de división de código (code-splitting)

Las versiones de Next.js anteriores a 9.2 tenían un conjunto fijo de paquetes JavaScript requeridos para cargar y hacer interactiva una página:

  • El archivo JavaScript de la página
  • Un archivo con JavaScript común
  • El paquete del runtime del lado del cliente de Next.js
  • El paquete del runtime del lado del cliente de Webpack
  • Importaciones dinámicas (agregadas a través de next/dynamic, cuando se usan)

Para que la página sea interactiva, todos estos paquetes deben cargarse ya que dependen unos de otros para iniciar React en el navegador.

Debido a que todos estos paquetes son necesarios para que la aplicación se vuelva interactiva, es importante que estén lo más optimizados posible. En la práctica, esto significa no descargar código en exceso de otras partes de la aplicación.

Por esta razón, Next.js usaba un paquete commons que contenía JavaScript común entre páginas. El cálculo de la antigua estrategia de división de paquetes para generar commons era una heurística de relación de uso. Si un módulo se usaba en más del 50% de todas las páginas, se marcaba como módulo común. De lo contrario, se incluía en el archivo JavaScript de la página.

Sin embargo, las aplicaciones pueden consistir en muchos tipos diferentes de páginas. Por ejemplo, páginas de marketing, un blog y un panel de control. Si había un gran número de páginas de marketing en comparación con otros tipos de páginas, el cálculo de comunes resultaría en optimizaciones enfocadas principalmente en las páginas de marketing.

Nuestro objetivo es optimizar para todos los tipos de páginas en una sola aplicación.

Alex Castle propuso un nuevo método de chunking (creación de archivos JavaScript separados) que permite una optimización de chunks comunes con múltiples archivos, incluso cuando hay muchos tipos de páginas involucrados.

Hoy, nos complace anunciar que este nuevo comportamiento de chunking está habilitado por defecto en Next.js 9.2. Nos gustaría extender nuestro profundo agradecimiento al equipo de Google Chrome y a Alex Castle por contribuir con este cambio. Este cambio refleja el esfuerzo acumulado de semanas de investigación, pruebas de laboratorio, pruebas en el mundo real e implementación.

La nueva implementación de chunking aprovecha HTTP/2 para entregar un mayor número de chunks de menor tamaño.

Bajo la nueva heurística, los chunks se crean para:

  • Un chunk mínimo para cada página.
  • Un chunk del framework que contiene React, ReactDOM, el Scheduler de React, etc.
  • Chunks de bibliotecas para cualquier dependencia de node_module mayor a 160kb (antes de minificar/gzip)
  • Un chunk común para código usado en todas las páginas.
  • Tantos chunks compartidos (usados por 2 o más páginas) como sea posible, optimizando para el tamaño general de la aplicación y la velocidad de carga inicial.
  • El runtime del lado del cliente de Next.js.
  • El runtime de Webpack.

Veamos qué significa esto en una aplicación del mundo real:

Un socio industrial que adoptó tempranamente, Barnebys®, vio una disminución del 23% en el tamaño general de la aplicación.

Además, su paquete JS más grande se redujo en un 30% — de 605kB a 425kB — sin cambios de código requeridos.

Otro socio industrial, SumUp®, vio una disminución del 70% en su paquete JS más grande — de 395kB a 122kB — sin cambios de código requeridos.

Paquete JavaScript más grande

AntesDespuésDiferencia
Barnebys605kB425kB30% más pequeño
SumUp395kB122kB70% más pequeño

El nuevo comportamiento de chunking no solo reduce el tamaño general y de carga inicial, sino también las navegaciones sucesivas del lado del cliente. Barnebys® vio una reducción del 87% en la cantidad de JavaScript cargado después de seis (6) navegaciones de página:

JavaScript cargado por múltiples transiciones del lado del cliente

AntesDespuésDiferencia
Barnebys136kB18kB87% más pequeño

Este nuevo comportamiento es completamente compatible con versiones anteriores. Actualizar a la última versión de Next.js es todo lo que necesita hacer para aprovechar esta mejora de rendimiento.

Rutas dinámicas catch-all

Con el lanzamiento de Next.js 9 introdujimos segmentos de ruta dinámicos con el objetivo de simplificar los segmentos dinámicos en Next.js sin necesidad de un servidor personalizado. Esta característica ha sido ampliamente adoptada por los usuarios de Next.js.

Todavía había algunos casos que la característica de segmentos de ruta dinámicos no cubría.

Uno de estos casos eran las rutas catch-all. Por ejemplo, enrutar un comodín como /post/** como una página. Esto es especialmente útil cuando tienes una estructura anidada definida por una fuente de contenido como un CMS.

Ahora puedes crear rutas dinámicas catch-all usando la sintaxis [...name].

Por ejemplo, pages/post/[...slug].js coincidirá con /post/a, /post/a/b, /post/a/b/c, y así sucesivamente.

slug se proporcionará en el objeto query del router como un array de partes individuales de la ruta. Entonces, para la ruta /post/foo/bar, el objeto query será { slug: ['foo', 'bar'] }.

Comunidad

Estamos muy emocionados de ver el crecimiento continuo en la adopción de Next.js:

  • Hemos tenido más de 880 contribuyentes independientes.
  • En GitHub, el proyecto ha recibido más de 44,000 estrellas.
  • El directorio de ejemplos tiene más de 220 ejemplos.

La comunidad de Next.js ahora tiene más de 13,800 miembros. ¡Únase a nosotros!

Estamos agradecidos con nuestra comunidad y todos los comentarios y contribuciones externas que ayudaron a dar forma a esta versión.