Hamburger Icon
Introducción a componentes de servidor con Next.js

Introducción a componentes de servidor con Next.js

En React v18 se introdujo el concepto de componente de servidor. Es algo que causó bastante revuelo por la novedad que suponía, pero, pasado un tiempo, ya está llegando el momento en que esto se normaliza y los frameworks que usan React se adaptan a ello.

Es el caso de Next.js, seguramente el primer framework que se nos viene a la cabeza cuando pensamos en React. Next.js v13 nos ha traído muchas novedades, pero una de las más destadas es la introducción por defecto de componentes de servidor, que son componentes que se renderizan en el backend.

Este post pretende ser una simple introducción al concepto de componente de servidor, sus ventajas y cuándo usarlos. Para ello, primero necesitamos entender las diferentes formas en que una página puede ser renderizada cuando usamos Next.js.

Renderizado de páginas

El renderizado es el proceso por el cual el código que escribes se convierte en la interfaz de usuario. Con Next.js tenemos a nuestra disposición diferentes formas de renderizar nuestra aplicación.

Renderizado a nivel de componente

Una aplicación se puede renderizar tanto en el servidor como en el cliente. Esto es así a partir de React 18. Antes, todo se renderizaba directamente en el cliente, lo cual provoca que, a veces, se requiera una carga imortante de código JavaScript en el navegador.

Desde que podemos usar componentes de servidor y componentes de cliente, tenemos el poder de decidir el entorno de renderizado que queramos a nivel de componente. Por defecto, los componentes definidos en el directorio app del proyecto se renderizarán en el servidor, de esta forma se reduce bastante la cantidad de código que se manda al cliente. Eso sí, si nos interesa, podemos definir componentes específicos que se rendericen en el cliente directamente.

Renderizado estático vs dinámico

Next.js nos da opciones para que podamos optimizar el renderizado en el servidor con la posibilidad de hacerlo de forma estática o dinámica.

Renderizado estático

Todos los componentes, los de servidor y los de cliente, se prerenderizan en el servidor en el momento de construir la aplicación (build time). El resultado se cachea y se reutiliza. Como cuando se usa un sitio generado estáticamente (SSG).

Los componentes se renderizan de forma un poco diferente dependiendo de si son de servidor o de cliente.

Los componentes de cliente son prerenderizados y cacheados en el servidor. El resultado se manda al navegador para la hidratación de la aplicación.

Los componentes de servidor se renderizan en el servidor y su resultado se usa para generar el HTML, luego, todo eso se usa para hidratar los componentes en el cliente. De esta forma no es necesario JavaScript desde el lado del navegador.

Renderizado dinámico

Con este tipo de renderizado, tanto los componentes de servidor como los de cliente son renderizados en el servidor en el momento de la petición, cuyo resultado no se cachea (Server-Side Rendering).

Componentes de servidor y de cliente

En un extremo tenemos el gran rendimiento que ofrece el renderizado en el lado del servidor, mientras que en el otro tenemos la gran interactividad que podemos ofrecer en el lado del cliente. Combinando componentes de servidor y de cliente podemos obtener como resultado una aplicación con lo mejor de los dos extremos.

Componentes de servidor

Como hemos comentado antes, todos los componentes dentro de la carpeta app del proyecto serán de servidor por defecto. Si usas Next.js, a partir de la versión 13, no necesitas hacer nada especial para usar este enfoque y beneficiarte del gran rendimiento que ofrece.

La principal ventaja de los componentes de servidor, que hace que ofrezcan un gran rendimiento, es que permiten que muchas dependencias de JavaScript, que antes era necesario gestionar desde el lado del cliente, se queden ahora en el lado del servidor y liberemos al navegador de esa carga. Podemos enviar JavaScript al cliente solo cuando se necesite una interactividad mayor con los componentes de cliente.

Componentes de cliente

Los componentes de cliente se renderizan en el navegador. Usando Next.js, este tipo de componentes se pueden prerenderizar en el servidor y ser hidratados en el cliente.

Qué es la hidratación de componentes

Ya se ha mencionado en este post un par de veces. Puede que te preguntes qué es eso de la hidratación. La hidratación de componentes no es más que una técnica que se usa que consiste en código JavaScript en el lado del cliente que añade dinamismo a una página HTML estática.

¿Cómo se añade este dinamismo? Pues a través de enlazar eventos a elementos HTML, como un clic, pasar el ratón por encima de una zona, al cargar una página, al redimensionarla...

Para conseguir dinamismo en el navegador es necesario, a priori, que tenga cierta carga de trabajo para conseguirlo. A través de la hidratación, conseguimos que haya dinamismo en el navegador ahorrándole esa carga.

Cómo usarlos

Cuando un compoente use algún hook de cliente, como useState por ejemplo, es necesario que en la zona superior del archivo del componente pongas "use client":

"use client" // con esto indicamos que se trata de un componente de cliente

import { useState } from "react"

const Button = () => {
  const [active, setActive] = useState(false)
}

const handleClick = () => {
  const newActive = !active
  setActive(newActive)
}

return (
  <button onClick={handleClick}>{active ? "is active" : "is disabled"}</button>
)

export default Button

¿Cuándo usar componentes de servidor o de cliente?

Los componentes de servidor se aconsejan para cuando:

  • se extraiga información de alguna API externa
  • se acceda únicamente a recursos del backend
  • queramos usar datos sensibles como API Keys o tokens
  • queramos mantener las dependencias en el servidor para reducir la carga en el cliente

Vamos a necesitar componentes de cliente cuando:

  • se necesite interactividad a través de eventos como onClick, onChange o similares
  • se necesite usar hooks de cliente como useState o useEffect
  • queramos utilizar API's del navegador
  • queramos usar hooks personalizados que dependan de hooks de cliente o de API's del navegador
  • se necesite usar los antiguos componentes de clase

Apunte sobre extracción de datos de API's externas

Aunque se puedan recoger datos conectando con API's externas directamente desde el navegador, se aconseja hacer esta recogida de datos en el servidor a no ser que haya un motivo concreto que obligue a hacerlo en el lado del cliente, ya que a la larga el rendimiento de la aplicación se beneficiará de ello.

Pasando datos entre componentes de servidor y de cliente

Se aconseja obtener los datos en el componente que los necesite en vez de pasarlos entre componentes, pero cuando esto no sea posible y necesitemos pasar información entre un componente de servidor y otro de cliente, lo haremos a través de propiedades, de componentes superiores hacia los inferiores, igual que hasta ahora.

La diferencia es que los datos que se pasen de un componente servidor a un componente cliente tienen que ser serializables, si no lo son no se pueden pasar de forma directa, como ocurre con las funciones o los objetos de fecha.

Resumen

Next.js es uno de los principales frameworks de los que te puedes beneficiar si usas React, aunque no es el único. Para no quedarse atrás, estre framework evoluciona y cada vez nos da más y mejores funcionalidades.

Ahora, a partir de Next.js v13, podemos decidir qué componentes se renderizarán en el servidor y cuáles en el lado del cliente. Esto nos da una flexibilidad enorme para que la aplicación funcione como un cohete sin que penalicemos reduciendo la interactividad de la misma.

Por defecto todos los componentes se renderizarán en el servidor, pero podremos indicar de forma explícita los componentes que se tengan que renderizar en el cliente.