6 formas de usar estilos en tus componentes React – Comparaciones, beneficios, desventajas y performance


6 formas de usar estilos en tus componentes React – Comparaciones, beneficios, desventajas y performance

Introducción

Existen distintas formas de aplicar estilos en componentes React y a veces la moda de usar librerías o utilizar practicas para hacer las cosas más fáciles o rápido, nos pueden hacer caer en la trampa de luego tener problemas a la hora de reutilizar, en la seguridad, en la performance, mantenimiento, diseño, etc.

Como digo siempre, es importante tener en cuenta a la hora de desarrollar software, la arquitectura, los patrones que nos permiten no reinventar la rueda, la seguridad, la reutilización, la facilidad de mantenimiento (el punto que siempre hago hincapié, me gusta ser practico) y la performance (algo fundamental para hermosas experiencias de usuario).

Escribo este post para evaluar que opciones pueden utilizarse para aplicar estilos en los componentes React y porque suele ser un problema la performance en sistemas robustos empresariales si no se elije una buena opción.

Elegir la mejor opción en cualquier desarrollo siempre va de la mano a lo particular que queremos hacer. Existen reglas generales, claro, como en todo, pero siempre hay que evaluar beneficios y consecuencias de lo que queremos aplicar en cómo y en qué. Hay que analizar los puntos que enumere anteriormente y para este caso lo principal seria la performance y el mantenimiento.

Cómo funciona el renderizado en una pagina web HTML?

Antes de entrar en detalles de que forma elegir para aplicar estilos en los componentes React, comencemos por como funciona el renderizado de una página para entender conceptos básicos de renderizado.

Para no complejizar y no entrar en tanto detalle en este post sobre como funciona una pagina HTML internamente, voy a resumir algunos conceptos para dar entendimiento macro y general.

Cuando un documento HTML se descarga de un servidor, ocurren varios procesos. El navegador procesa el HTML en varios otros procesos y luego aplica los estilos y dibuja.

Primero, convierte el HTML en el DOM. El DOM es la representación del contenido de la pagina en la memoria del navegador. En ese momento también analiza todo lo relacionado a la pagina, como imágenes y cualquier otro contenido, luego continua con los estilos y finalmente con el scripting de Javascript.

Luego, el navegador analiza el CSS y lo organiza en distintas unidades, es decir, según las reglas que deben aplicarse en base a los selectores que se especificaron. Esta etapa se la denomina árbol de renderización, ya que para cada tipo de selector (elementos, clases, IDs) calcula todas las reglas que debe aplicarle y se genera un árbol con todos los nodos para saber como debe aplicarlos en la pagina.

Una vez que el navegador organizo el DOM y el árbol de renderizado, lo que ocurre es que comienza a barrer el DOM para asociar las reglas que debe aplicar a cada nodo del DOM. Si hay un error o una regla no la entiende, la ignora.

Luego que las reglas son aplicadas, el navegador comienza a dibujar. El motor de renderizado (cada navegador tiene el suyo) dibuja el HTML y termina de aplicar los estilos.

Luego aparece el scripting, todo lo que en el HTML indica que hay que ejecutar un script, es ejecutado.

Hasta este momento en cuanto a performance, podemos analizar dos cuestiones: el loading y el scripting execution.
El loading es todo el tiempo que ocurre entre que el navegador detecta la descarga de un recurso y su carga en el navegador y el scripting execution todo el tiempo que ocurre entre que comienza un script y finaliza.
Aquí es donde surge el WPO, que es la técnica de optimizar estos tiempos que incluyen la optimización de Javascript, evitar re dibujar elementos de la pagina, evitar reglas o CSS complejo, optimizar efectos, animaciones y «lag» entre comportamientos y evitar un DOM complejo y mal estructurado.

Además de todo lo explicado hasta aquí, tenemos una cuestión más: cuando el scripting se ejecuta, también puede modificar el DOM y los estilos aplicados. Esto ya no sería una aplicacion de estilos nativa, sino que seria «manipulación» y según como se manipule, puede darnos resultados no deseados.

Esto nos termina definiendo que según como apliquemos nuestro «styling» y organicemos el DOM podemos obtener diferentes resultados y diferente performance.

Como afecta el «styling» en la performance según como lo apliquemos?

Como te habrás dado cuenta o podido deducir, tenemos 4 variables que nos pueden afectar: el diseño en si de los elementos de la pagina, las reglas de estilo aplicadas, los tiempos de carga de la composición de la pagina y los tiempo de ejecución de los script (que afectan al DOM y a los estilos).

Hoy en día con el auge de librerías y frameworks de trabajo para componentes del frontend, es muy común utilizar todo el tiempo librerías para facilitarnos estas tareas o al componentizar el desarrollo del frontend, existe una gran manipulación del DOM y de las reglas de estilos.

Recordá que todo lo que es manipulado por scripting, siempre insume más tiempo que descargar hojas de estilo y aplicar nativamente los estilos. Además los navegadores tienen optimizaciones relacionadas al uso de hojas de estilo (como el caching), aunque todo lo que es manipulado, también ademas inyecta o incluye librerías de optimización (que siempre le suman tiempos de carga y consumo de recursos al navegador).

Como aplicar estilos cuando usamos componentes en React?

Lo que sigue a continuación no es la verdad absoluta. No hay soluciones absolutas ni para todo, ni para nada particular. Cada situación necesita ser analizada en base a lo que queremos desarrollar y en este caso particular hay que analizar la performance y la mantenibilidad para saber que elegir en que caso y para qué. Nuestra mejor opción dependerá de nuestro análisis. Pero en términos generales, podríamos analizar estas formas de aplicar estilos y en que nos puede afectar más o menos, según el caso.

Para cada caso voy a analizar en términos generales: las dependencias, dificultad de aprendizaje, mantenibilidad, si es buena elección y la performance.

Recordá que utilizar manipulación de estilos no es la mejor opción, si analizas la performance (con algún profiler en el navegador) en todos los casos manipular estilos con JS suma recursos utilizados y memoria. En elementos sencillos puede afectar en solo un rango de 1 a 10 ms más por componente y no preocupa a los desarrolladores ni a los usuarios, son mili segundos que no nos preocupan y que tampoco se exponencian, a nadie le afecta que en un total de componentes de una pagina, si toda la suma da 500ms más, casi no es percibible , en otros más complejos puede sumar hasta 100ms por componente y en componentizaciones con elementos hijos y relaciones puede incrementar hasta segundos! y muchos!

LO PEOR QUE VI FUE QUE USABAN CSS-in-JS (con styled components) en una grilla y con 10 elementos consumía de 5 a 6 segundos y a medida que scrolleabas y se cargaban más elementos se exponenciaba haciendo que la grilla al tener más de 200 elementos llegue a insumir unos 20 segundos para renderizar 10 elementos más (y no estoy contando los fetchs! JAJA)

Inline CSS

Todos los programadores sabemos y estamos acostumbrados que nos digan «no uses estilos inline», ya es una muletilla, algunos lo dicen por decir, otros con real fundamento y experiencia, pero si, todos sabemos que no es la mejor opción.
Para el que no sabe, es la forma de indicar en el HTML directamente en el elemento el estilo que queremos aplicar.
Hace que el código sea ilegible, difícil de mantener (no imposible) y presta a confusiones, ademas ni hablar que no permite organizar los estilos ni reutilizarlos.

En React lo podes usar de 2 formas, veamos algo de código:

Este caso implica un procesamiento por JS (utiliza scripting):

Dependencias? NO Dificultad? FACIL Eleccion? La peor Mantenibilidad? COMPLEJA Performance? Buena

Normal CSS

Este caso es la aplicacion normal de estilos en base a las plantillas de estilos (CSS) usando los className en los componentes o directamente importando o no las hojas de estilos y aplicándolas directamente a los elementos.
Todos sabemos que utilizar bien los CSS es muy beneficioso, es nativo para el navegador, no tenemos dependencias que nos bloqueen, no hay que aprender nada extra, es mucho mas fácil de administrar, etc.
Cuando más nos sirve es cuando hay un maquetador o una persona responsable de los estilos y NO cae la responsabilidad en el desarrollador. El desarrollador normalmente no organiza bien los estilos o no los aplica bien, por eso prefiere el código o técnicas de CSS-in-JS.
Esta sería mi mejor opción cuando hay un responsable de estilos o un maquetador que solo debe indicar al programador que aplicar cuándo y cómo.

Veamos algo de código:

Este caso mucho más performante NO implica ningún procesamiento por JS (y el ejemplo incluye para un caso que dependemos de variables para aplicar un estilo u otro, pero el estilo no se aplica por JS):

Dependencias? NO Dificultad? MUY FACIL Elección? MUY BUENA Mantenibilidad? FACIL Performance? MUY BUENA


CSS-in-JS

Esta técnica es utilizar JS para aplicar los estilos. Todo se crea por JS. Se aplica luego que el render nativo ya se aplico y al ejecutarse los scripts de JS. Es decir, todo ocurre en JS, sumando memoria y procesamiento.
Algo interesante es que lo que ocurre es que JS crea tags de style a medida que crea los estilos y los adjunta al DOM para referenciarlo a los elementos. Esto en pequeños componentes no es un problema, pero en casos como dashboard, gráficos (barras, etc), formularios complejos, componentes dinámicos y con muchos efectos, grillas, etc, suma mili segundos que en un total puede ser faltal o freezar constantemente nuestro navegador. Aplica a buenos casos, pero no a todo, hay que saber cuando elegirlo. Si es bueno para cuando tenes muchas cuestiones dinámicas (en base a estados de los componentes el style cambia, es decir, es condicional) y para separar los estilos en el componente en si (para las librerías es ideal, porque no necesita que configures nada extra o tengas una hoja de estilo o varias grandes con cosas que quizás no utilizas cuando solo querés un solo componente). He visto casos que utilizan material-ui y luego componentes de otras librerías y en una misma pagina ocurren desastres de performance. Mismo con grillas complejas o dashboards complejos o gráficos de barras o dinámicos.
Como ventaja podemos decir que nos permite separar la unidad del componente con estilos incluidos, pero en cuanto a mantenibilidad quizás no es lo mejor y en performance no es una buena opción, todo lo que sea aplicado por JS siempre insume más.
Existen varias librerías para usar CSS-in-JS, la más conocida son los styled components que le dedicare un apartado más adelante.

Dependencias? SI, DEPENDE DE QUE USEMOS Dificultad? MEDIA Elección? MEDIA Mantenibilidad? MEDIA Performance? DEPENDE EL CASO, PERO SIEMPRE ES MAS COSTOSO QUE CUALQUIER TÉCNICA DE CSS

JSS (CSS-in-JS library)

A diferencia de otras librerías de CSS-in-JS es la más liviana y viene dentro de los paquetes de React oficiales. Pero a veces suele ser complejo y para la mayoría de los programadores con poca experiencia u otra experiencia de frontend puede ser complejo utilizarla. En performance es la mejor de CSS-in-JS pero los Styled-Components tomaron más popularidad por su sintaxis.

Dependencias? SI Dificultad? MEDIA-ALTA Elección? MEDIA Mantenibilidad? COMPLEJA Performance? MEDIA

Styled-Components (CSS-in-JS library)

A diferencia de otras librerías CSS-in-JS no hace falta cambiar las propiedades que tienen ‘-‘ a camelCase. Permite un mejor manejo lo de lo dinámico y cuando renderiza mantiene la unidad del componente mejor en el DOM, sin complejidad para asociar un componente como hacen otras librerías, pero al mismo tiempo añade complejidad en la manipulación y agrega 2 «Context.Consumer» extras por componente. En componentes complejos, la baja performance se destaca y solo es una buena opción para un determinado tipo de paginas web.
Siempre que analice performance con styled-components he detectado un 50% de tiempo extra mínimo comparado a hacer lo mismo con CSS normal. Reconozco que puede ser por como desarrollan los componentes o la experiencia del desarrollador, pero en ejemplos basicos de renderizar listas sencillas, tablas, elementos sueltos, etc, solo a modo de prueba de performance algo que con CSS tarda 1ms con style-components puede llegar a 5ms o un poco más. En páginas complejas puede ser un problema (incluso cuando hay relación de objetos para refrescarse, se multiplica).

Dependencias? SI Dificultad? MEDIA-ALTA Elección? MEDIA Mantenibilidad? COMPLEJA Performance? BAJA

CSS Modules

Los CSS modules son parecidos a los mixins de SASS y permite la combinación de múltiples estilos y al mismo tiempo separar los estilos solo para los componentes y no tener CSS globales, aplicando solo a los componentes que lo usan.
Pero también usan JS para procesarse. A un nivel más bajo y con meno uso de recursos y dependencias que un CSS-in-JS pero aun así sigue utilizando JS.
Esta libreria permite indicar un archivo especifico css para el componente y React solo cargara ese estilo para ese componente y mapeara las clases del css a Javascript para luego permitirte acceder directamente desde codigo.

Veamos un ejemplo:

Dependencias? SI Dificultad? BAJA Elección? MEDIA Mantenibilidad? SIMPLE Performance? BUENA

SASS, SCSS y LESS

Estos son preprocesadores de CSS, es decir, una herramienta que nos permite con otra sintaxis agregar funcionalidad extra (o mágica como sus fanáticos dicen) para permitir manipular los CSS de mejor forma y luego trasformar a CSS sin nosotros tener que preocuparnos.
Permite usar variables y código extra para manipular estilos y compilar en un CSS final.
En lo que afecta o implica usarlo en React no cambia prácticamente en nada, solo debemos importarlo como si lo hiciésemos con un CSS.
Aplicarlo es lo mismo que cuando usamos un CSS normal o con los CSS Modules (en cuanto a uso en React dentro del componente), con los className. Importamos el archivo y luego aplicamos el className que queremos usar.

Dependencias? SI Dificultad? BAJA-MEDIA Elección? MEDIA Mantenibilidad? SIMPLE Performance? BUENA

Stylable

Es un preprocesador, seria como TypeScript lo es para Javascript. Nos permite ir tipando los estilos y utilizarlos directamente dentro de los componentes de React. Tiene complejidad y admite distintas formas de implementarlo y por eso no suele ser la opción más buscada. La ventaja quizás es que nos separa los CSS en distintos files para solo linkearlos y asociarlos al componente donde estamos invocándolo. No hay gran comunidad interesada en Stylable y puede ser engorroso para desarrolladores sin o con poca experiencia utilizar Stylable (y menos para los que les gusta googlear todo porque no hay casi nada de documentación comparado al resto de los métodos de styling).

Dependencias? SI Dificultad? ALTA Elección? BAJA Mantenibilidad? COMPLEJA Performance? BAJA-MEDIA

Conclusión

Para este análisis me base en mi experiencia, en pruebas que suelo hacer de performance de aplicaciones SPA o frontends y en las ventajas y desventajas que ofrece cada opción.

Algunas se pueden aplicar juntas o para cada caso que necesitemos, otras podrían generar un problema al hacer esto y algunas aplican para casos particulares que nos pueden facilitar las cosas.

Ninguna es la elegida de base, aunque uno pueda tener preferencias, dependerá de tu proyecto.

Yo particularmente no me inclino a preprocesamiento o procesamiento en linea con Javascript, prefiero utilizar CSS o SASS/SCSS o cualquier cosa que no incluya proceso de JS. Puede ayudar a la programación pero no ayuda a la mejor utilización de las herramientas y los estándares de programación. Pero como ya dije antes, siempre dependerá del proyecto, del equipo y de las cosas que queremos solucionar, como ocurre con toda solución.

About the author: Matías Creimerman
Matías Creimerman
I’m a specialist in design, development and management of software solutions with almost 20 years of experience. Microsoft Certificated Professional (MCP). Expert in dot net and Microsoft technologies. Experience and skills in designing solutions in a wide range of commercial, industrial and production areas. Design of architectures, software applications and processes. Skills in leadership and team management. Tech trainer. Technology researcher. Self-taught and dedicated to continuous learning. Skills in estimation, quotation, projects proposals and solutions design. Entrepreneurial spirit. Strong Tech profile but also customer oriented. I perform roles as fullstack dev, tech consultant, technical referent, development leader, team leader, architect, cross leader, tech manager, tech director, trainer, ramp-up & follow-up teams, software factory manager, DevOps and release manager. Regular chess player and musician.
Professional Website In Blogger Github About Me Portfolio Wordpress - Arquitectura y desarrollo de software Wordpress - Personal Blog Microsoft - Youracclaim Badges Microsoft - Tech Profile Microsoft - ASP.NET Forum tw
Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License Creative Commons License
This content is property of Matias Creimerman Any misuse of this material will be punishable
This work is licensed under a International Copyright Law protects «original works of authorship»
including photographs, videos, and blog posts posted on social media sites
The content has no rights to be shared without authorization or citation to the author.
This content cannot be sold be adapted or modified partially or totally.
All content shared outside this blog that doesn’t belong to the author must have citations to the author.

Deja un comentario