¿Qué son Server Components de React y cómo se relacionan con SSR/SSG/ISR?

Ayer el team de React anunció un nuevo feature, super, experimental, voy a intentar explicar de que trata, pero primero vamos a definir algunos conceptos para estar todos en la misma, CSR, SSR, SSG y ISR

Client-side Rendering (CSR) es la forma normal de usar React, hacemos un bundle de JS con nuestros componentes, React, ReactDOM, hacemos render y listo, todo funciona en el navegador. Todo el HTML se genera ahí mismo

Server-side Rendering (SSR) es tomar estos mismo componentes de React y hacer render en el servidor al recibir una petición, este render genera un string de HTML que se envia al navegador para que lo muestre, después se carga el JS y se hace CSR como siempre

Static Site Generation (SSG) es hacer lo que hace SSR pero al momento de hacer el build de la app en vez de que cada petición, esto esta bueno para evitar montar un servidor, pero es posible solo si el contenido es público y más o menos estático (ej. blog, e-commerce, landings)

Incremental Static Regeneration (ISR) es hacer SSG, pero manteniendo un servidor corriendo que pueda, cada tanto, hacer SSR, esto permite tener el performance de SSG con la capacidad de actualización de SSR, que con SSG requeriría un nuevo build (usualmente asociado a un deploy)

Con esto explicado, los nuevos Server Component que anunciaron no tiene nada que ver con todo lo anterior, la idea acá no es hacer SSR/SSG/ISR ya que esto siempre se pudo, desde hace varios años, incluso sin Next/Remix/Gatsby. La idea es reducir el bundle de JS

Al crear una app hay muchos componentes que no son totalmente dinámicos, componentes que simplemente reciben algunos props y los renderizan, o hacen un fetch y renderizan esa data y otros componentes capaz más dinámicos

Que hace a un componente dinámico? Por ejemplo tener estados propios o tener efectos. En estos casos el componente necesita ejecutarse en el navegador para poder funcionar. Pero los componentes más estáticos en realidad no lo necesitan

La idea de los Server Component es poder decirle a React "este componente X no es dinámico" y entonces React (el bundler en realidad) va a evitar agregar ese componente a tu bundle de JS, por lo que el usuario ya no descargaría nada del JS de ese componente

¿Cómo hace React entonces para renderizarlo? Cuando React necesite el HTML de este componente va a hacer una petición a un servidor que va a generar una especie de JSON con la respuesta, esta incluye que etiquetas HTML renderizar y si es necesario un componente dinámico

React recibe esta respuesta, que llega como un stream para no esperar a que este completa, y va renderizando, si hay un componente dinámico (aka Client Component) este se renderiza en el navegador, la respuesta incluye también que props debe React pasar a este Client Comoponent

Con esto, el bundle de JS se va a reducir un montón ya que ahora solo se va a enviar React, React DOM y tus Client Component, más las dependencias de estos. Que pasa si un Server Component depende de alguna librería externa? Esta se queda en el servidor y no se suma al bundle

Ahora… Al mover algunos componentes al servidor abre la puerta a usar APIs del servidor que no estaban disponibles en el navegador, un Server Component podría hacer un fetch a un API directo desde el servidor o incluso podría hacer una query directa a la base de datos

Esto nos permitiría crear componentes Client que usen API del navegador y componentes Server que usen API del servidor. El poder leer datos desde el mismo servidor incluso ayudaría a reducir la cascada de peticiones que normalmente ocurre en el navegador

Esto es posible porque una petición de localhost a localhost sería muy rápida, cuestión de ms, en vez del tiempo normal que toma a un navegador comunicarse con un API.

¿Cómo afecta todo esto a SSR/SSG/ISR? En primera instancia no afectaría, simplemente al hacer cualquiera de estos algunos componentes serían Server y otros Client así que tendrían que saber leer el output de los Server Component para generar el HTML y listo, el resto no cambia

Para terminar

  • ¿Necesito aprender esto ahora? No, es 100% experimental
  • ¿Va a afectarme de alguna forma? No en el corto plazo
  • ¿Cómo afecta a frameworks como Next? Next va a soportar esto de forma nativa