Lado del cliente frente al lado del servidor frente a la renderización previa para aplicaciones web
Publicado: 2022-03-11Recientemente, algo está sucediendo dentro de la comunidad front-end. El renderizado del lado del servidor está ganando más y más tracción gracias a React y su función de hidratación del lado del servidor incorporada. Pero no es la única solución para brindar una experiencia rápida al usuario con una puntuación de tiempo hasta el primer byte (TTFB) súper rápida: la representación previa también es una estrategia bastante buena. ¿Cuál es la diferencia entre estas soluciones y una aplicación totalmente renderizada por el cliente?
Aplicación renderizada por el cliente
Dado que existen marcos como Angular, Ember.js y Backbone, los desarrolladores front-end han tendido a renderizar todo del lado del cliente. Gracias a Google y su capacidad para "leer" JavaScript, funciona bastante bien e incluso es compatible con SEO.
Con una solución de renderizado del lado del cliente, redirige la solicitud a un solo archivo HTML y el servidor lo entregará sin ningún contenido (o con una pantalla de carga) hasta que obtenga todo el JavaScript y deje que el navegador compile todo antes de renderizar el contenido.
Con una conexión a Internet buena y confiable, es bastante rápido y funciona bien. Pero puede ser mucho mejor, y no tiene que ser difícil hacerlo de esa manera. Eso es lo que veremos en los siguientes apartados.
Representación del lado del servidor (SSR)
Una solución SSR es algo que solíamos hacer mucho, hace muchos años, pero que tendemos a olvidar en favor de una solución de renderizado del lado del cliente.
Con las antiguas soluciones de representación del lado del servidor, creabas una página web, con PHP, por ejemplo, el servidor compilaba todo, incluía los datos y entregaba una página HTML completa al cliente. Fue rápido y efectivo.
Pero… cada vez que navegaba a otra ruta, el servidor tenía que hacer el trabajo de nuevo: obtener el archivo PHP, compilarlo y entregar el HTML, con todo el CSS y JS retrasando la carga de la página a unos pocos cientos de ms o incluso segundos enteros.
¿Qué pasaría si pudiera cargar la primera página con la solución SSR y luego usar un marco para hacer enrutamiento dinámico con AJAX, obteniendo solo los datos necesarios?
Esta es la razón por la que SSR está ganando cada vez más tracción dentro de la comunidad porque React popularizó este problema con una solución fácil de usar: el método RenderToString
.
Este nuevo tipo de aplicación web se denomina aplicación universal o aplicación isomorfa . Todavía existe cierta controversia sobre los significados exactos de estos términos y la relación entre ellos, pero muchas personas los usan indistintamente.
De todos modos, la ventaja de esta solución es poder desarrollar una aplicación del lado del servidor y del lado del cliente con el mismo código y brindar una experiencia realmente rápida al usuario con datos personalizados. La desventaja es que necesita ejecutar un servidor.
SSR se utiliza para obtener datos y rellenar previamente una página con contenido personalizado, aprovechando la conexión a Internet fiable del servidor. Es decir, la propia conexión a Internet del servidor es mejor que la de un usuario con lie-fi), por lo que puede obtener previamente y fusionar datos antes de entregarlos al usuario.
Con los datos rellenados previamente, el uso de una aplicación SSR también puede solucionar un problema que tienen las aplicaciones renderizadas por el cliente con el uso compartido social y el sistema OpenGraph. Por ejemplo, si solo tiene un archivo index.html
para entregar al cliente, solo tendrá un tipo de metadatos, muy probablemente los metadatos de su página de inicio. Esto no se contextualizará cuando desee compartir una ruta diferente, por lo que ninguna de sus rutas se mostrará en otros sitios con su contenido de usuario adecuado (descripción e imagen de vista previa) que los usuarios deseen compartir con el mundo.
Pre-renderizado
El servidor obligatorio para una aplicación universal puede ser un impedimento para algunos y puede ser excesivo para una aplicación pequeña. Esta es la razón por la que el prerenderizado puede ser una muy buena alternativa.
Descubrí esta solución con Preact y su propia CLI que le permite compilar todas las rutas preseleccionadas para que pueda almacenar un archivo HTML completo en un servidor estático . Esto le permite brindar una experiencia súper rápida al usuario, gracias a la función de hidratación Preact/React, sin necesidad de Node.js.
El problema es que, debido a que esto no es SSR, no tiene datos específicos del usuario para mostrar en este punto, es solo un archivo estático (y algo genérico) enviado directamente en la primera solicitud, tal como está. Entonces, si tiene datos específicos del usuario, aquí es donde puede integrar un esqueleto bellamente diseñado para mostrarle al usuario que sus datos están llegando, para evitar cierta frustración de su parte:
Hay otra trampa: para que esta técnica funcione, aún necesita tener un proxy o algo para redirigir al usuario al archivo correcto.

¿Por qué?
Con una aplicación de una sola página, debe redirigir todas las solicitudes al archivo raíz y luego el marco redirige al usuario con su sistema de enrutamiento incorporado. Entonces, la carga de la primera página es siempre el mismo archivo raíz.
Para que funcione una solución de renderizado previo, debe decirle a su proxy que algunas rutas necesitan archivos específicos y no siempre el archivo raíz index.html
.
Por ejemplo, supongamos que tiene cuatro rutas ( /
, /about
, /jobs
y blog
) y todas ellas tienen diseños diferentes. Necesita cuatro archivos HTML diferentes para entregar el esqueleto al usuario que luego permitirá React/Preact/etc. rehidratarlo con datos. Entonces, si redirige todas esas rutas al archivo raíz index.html
, la página tendrá una sensación desagradable y con fallas durante la carga, por lo que el usuario verá el esqueleto de la página incorrecta hasta que termine de cargarse y reemplace el diseño. Por ejemplo, el usuario podría ver el esqueleto de una página de inicio con una sola columna, cuando solicitó una página diferente con una galería similar a Pinterest.
La solución es decirle a su proxy que cada una de esas cuatro rutas necesita un archivo específico:
-
https://my-website.com
→ Redirigir al archivo raízindex.html
-
https://my-website.com/about
→ Redirigir al archivo/about/index.html
-
https://my-website.com/jobs
→ Redirigir al archivo/jobs/index.html
-
https://my-website.com/blog
→ Redirigir al archivo/blog/index.html
Es por eso que esta solución puede ser útil para aplicaciones pequeñas: puede ver lo doloroso que sería si tuviera unos cientos de páginas.
Estrictamente hablando, no es obligatorio hacerlo de esta manera, simplemente podría usar un archivo estático directamente. Por ejemplo, https://my-website.com/about/
funcionará sin ninguna redirección porque buscará automáticamente un index.html
dentro de su directorio. Pero necesita este proxy si tiene direcciones URL param: https://my-website.com/profile/guillaume
deberá redirigir la solicitud a /profile/index.html
con su propio diseño, porque profile/guillaume/index.html
no existe y generará un error 404.
En resumen, hay tres vistas básicas en juego con las estrategias de renderizado descritas anteriormente: una pantalla de carga, un esqueleto y la página completa una vez que finalmente se renderiza.
Dependiendo de la estrategia, a veces usamos las tres vistas y, a veces, saltamos directamente a una página completamente renderizada. Solo en un caso de uso nos vemos obligados a utilizar un enfoque diferente:
Método | Aterrizaje (p. ej. / ) | Estático (p. ej /about ) | Dinámica fija (por ejemplo /news ) | Dinámico parametrizado (p. ej /users/:user-id ) |
---|---|---|---|---|
renderizado por el cliente | Cargando → Completo | Cargando → Completo | Cargando → Esqueleto → Completo | Cargando → Esqueleto → Completo |
Pre-renderizados | Completo | Completo | Esqueleto → Completo | HTTP 404 (página no encontrada) |
Prerenderizado con proxy | Completo | Completo | Esqueleto → Completo | Esqueleto → Completo |
RSS | Completo | Completo | Completo | Completo |
La representación solo del cliente a menudo no es suficiente
Las aplicaciones renderizadas por el cliente son algo que debemos evitar ahora porque podemos hacerlo mejor para el usuario. Y hacerlo mejor, en este caso, es tan fácil como la solución de renderizado previo. Definitivamente es una mejora sobre la representación solo del cliente y más fácil de implementar que una aplicación totalmente renderizada del lado del servidor.
Una aplicación SSR/universal puede ser realmente poderosa si tiene una aplicación grande con muchas páginas diferentes. Permite que su contenido sea enfocado y relevante cuando habla con un rastreador social. Esto también es válido para los robots de los motores de búsqueda, que ahora tienen en cuenta el rendimiento de su sitio al clasificarlo.
Estén atentos a un tutorial de seguimiento, en el que explicaré la transformación de un SPA en versiones prerenderizadas y SSR, y compararé su rendimiento.