Server Components vs Server Side Rendering

Server Components vs Server Side Rendering

¿Qué son los React Server Components y en qué se diferencia de Server Side Rendering?

En este artículo trataremos de aclarar las diferencias que existen entre React Server Components y Server Side Rendering (SSR) puesto que se trata de dos conceptos que en la superficie parecen muy similares puesto que los dos ocurren en el servidor y su objetivo final es ser capaces de renderizar el contendio que ofrecen de la forma más rápida posible.

Sin embargo en la propia documentación de los Server Components se nos está informando de que se trata de dos tecnologías complementarias y que cada una de ellas opera a distintos niveles en el servidor de tal manera que podemos combinar SSR y Server Components o trabar con cualquiera de ellos por separado.

Pero ¿qué es lo que los hace diferentes? Pues para entenderlo vamos a fijarnos, aunque pueda parecer un poco estúpido al principio, en aquellas dos partes de su nombre que los hace diferentes quedándonos con el Rendering en el caso de Server Side Rendering y Components en el caso de los Server Components.

Nuestra aplicación tiene una cabecera Header donde mostraremos la imagen del Profile del usuario, un menú lateral SideNav, un pie de página Footer y la lista de todos los TODOS en el centro del MainPanel gracias al uso de componente TodoComponent. De hecho, si representamos esta estructura de componentes como un árbol nos quedará algo como lo que podemos ver en la siguiente imagen:

En esta representación en la forma de árbol además hemos recogido que el componente TodoComponent está renderizando cada uno de los TODO gracias a la utilización de un componente TodoItem.

Server Side Rendering

Cuando Next JS (previo a la versión 13) realiza el Server Side Rendering de nuestra aplicación lo que viene a hacer es una renderizado en el servidor de lo que se vería en el cliente partiendo de un punto de partida en la jerarquía de componentes que hemos visto muy específico que será el componente Page (la raíz del árbol). ¿Qué quiere esto decir? Pues que todo el árbol de componentes que hemos mostrado anteriormente en la imagen será renderizado en su totalidad.

Esto tiene una serie de ventajas si lo comparamos con aquellas aplicaciones que no utilizarán SSR:

  1. La carga inicial de la aplicación será mucho más rápida puesto que el cliente de nuestra aplicación recibirá únicamente el código HTML que le va a permitir renderizar la página.

  2. Esta aproximación página será SEO-friendly puesto que los buscadores van a poderla rastrear teniendo el código HTML en su totalidad lo que incrementará su SEO.

  3. El tiempo de carga de la aplicación en el navegador del cliente se verá especialmente reducido puesto que junto con el código HTML además se le proporcionará el código JavaScript que le ayudará a realizar la funcionalidad que es propia de las interacciones que se vayan a realizar desde el navegador del cliente.

Sin embargo SSR tiene una desventaja que está relacionada con el último punto que acabamos de mencionar puesto que las aplicaciones web normalmente necesitan de una interacción por parte del usuario y esta solamente va a ser posible si en el lado del cliente (client-side) se produce un proceso de hidratación.

Server Components

Es en el proceso de hidratación que se tiene que llevar a cabo por parte del cliente donde viene a jugar su papel fundamental los Server Components. De hecho en el nombre de Server Components la palabra Server no es la que viene a denotar las nuevas funcionalidades que nos ofrece sino que lo realmente interesante es la palabra Component.

Así cuando estamos hablando de SSR lo que sucede es que se estará renderizando el árbol completo de componentes en el servidor (todos los componentes) y como resultado de este proceso se retornará la página completa. Como podemos imaginar esta aproximación es perfecta cuando estamos hablando de la carga inicial de nuestras páginas en el navegador de un usuario pero para nada ofrecerá una ventaja en el caso de que se tengan que hacer actualizaciones de esta misma página.

Nota: SSR no nos ayudará demasiado en el momento en el que estemos haciendo recargas de la misma página siendo solamente útil en el momento de la primera carga de la página.

Los Server Components son realmente interesantes puesto que nos van a permitir renderizar componentes de forma individual dentro del árbol de componentes de nuestra página puesto que estos no generan HTML de forma directa (veremos qué es lo que genera dentro de un momento).

Pero ¿por qué es Component la parte importante del nombre de esta tecnología? Pues pensemos un momento en cómo están construidas nuestras aplicaciones web ya que en la mayoría de las veces nos encontraremos con que dentro de una página la mayoría de los componentes que la forman no se verán actualizados de forma frecuente (de hecho se pueden llegar a considerar como estáticos) o al menos el número de actualizaciones que reciben son más bien pocas.

Asi, en nuestra aplicación de ejemplo, podemos pensar que el componente Header, el SideNav y el Footer pasarán a ser componentes estáticos en el momento en el que se pasa la carga de datos inicial puesto que la parte que es realmente dinámica es el contenido que está recogido dentro del componente TodoComponent.

Gracias al uso de los Server Components vamos a tener la capacidad de poder añadir o eliminar TODO de la lista que se está mostrando en la interfaz y solamente se actualizará en el servidor aquella parte de la página en la que esta información es relevante, es decir, el component TodoComponent.

Los Server Components nos van a permitir actualizar aquellas partes de nuestro código únicamente en el momento en el que lo necesitamos.

Con este mecanismo obtendremos una serie de ventajas:

  1. Seremos capaces de realizar actualizaciones muy precisas lo que implicará que la cantidad de información que se intercambiará con el navegador del cliente será menor proporcionándole únicamnete aquella parte del HTML que se ha visto modificada.

  2. Tenemos menos código en la parte cliente porque los Server Components ya sabemos que viven en el servidor sin necesidad de ningún código del navegador.

  3. La petición de los datos (data fetching) es mucho más sencilla e incluso podemos decir que se realiza de una forma mucho más racional puesto que cada uno de los Server Components será responsable de obtener la información que precisan.

Nota: recordemos que antes de los Server Components necesitábamos tener todos los datos que se precisan para renderizar el árbol de los componentes en el componente Page (es decir, en el componente raíz de toda la jerarquía de componentes) haciendo uso del método getServerSideProps y no solamente eso sino que estos datos deberían ser pasados hacia abajo en la jerarquía de componentes hasta llegar al que realmente los usa mediante técnicas como prop drilling.

Si nos paramos a pensar un poco más en lo que estamos estudiando veremos que todavía nos falta una pieza del puzzle que nos ayude a aclarar qué son los Server Components. Puesto que no estamos renderizando todo el código HTML de la página en el servidor ¿cómo es posible que el navegador sepa cómo actualizar el código HTML que está asociado a un Server Component?

Aquí es donde volvemos a hacer referencia a la afirmación que hemos hecho anteriormente donde afirmábamos que los Server Components no producen como salida código HTML por defecto sino que lo que viene a producir es algo como lo que se puede ver en la siguiente imagen donde se muestra un texto que sigue un determinado formato que se puede enviar gracias a un stream (_streamable text format_):

Como podemos observar este formato no es un JSON sino más bien sigue un formato conocido como JSON BLOB que es mucho más óptimo para que sea enviado a través de un stream mediante una comunicación HTTP.

Pero ¿qué pasa en el parte cliente? Pues que habrá una parte dentro de la aplicación cliente (un código JavaScript) que se encargará de deserializar este formato JSON BLOB y convertirlo en código HTML:

Lo que tenemos que tener claro es que este código JavaScript que se encargará de realizar la deserialización es genérico entendiendo como tal que no está vinculado con ninguno de los componentes que forman parte de nuestra aplicación.

De hecho si lo comparamos con la técnica de hidratación que se utilizada anteriormente en Next JS antes de la aparación de los Server Components, este mecanismo que tenemos ahora es mucho más ligero y enfocado a puntos concretos de nuestra aplicación lo que nos permitirá actualizar secciones precisas dentro de la interfaz sin tener que sacrificar velocidad o la seguridad de nuestras aplicaciones puesto que, una vez más, la palabra interesante del nombre de los Server Components es Component.