• No se han encontrado resultados

Una herramienta para mejorar la legibilidad de aplicaciones React

N/A
N/A
Protected

Academic year: 2020

Share "Una herramienta para mejorar la legibilidad de aplicaciones React"

Copied!
84
0
0

Texto completo

(1)

Trabajo Final

Ingeniería de Sistemas

Facultad de Ciencias Exactas

Universidad Nacional del Centro de la Provincia de Buenos Aires

UNCPBA

Abril 2018

Tema:

Una herramienta para mejorar la legibilidad de aplicaciones React

Alumno:

Fernández Cocirio, Mariano

Director:

Dr. Vidal, Santiago

(2)

Índice:

Capítulo 1: Introducción 8

1.1 Desarrollo de páginas web en la actualidad 8

1.2 Una herramienta para mejorar la legibilidad de aplicaciones React 10

1.3 Caso de estudio 12

1.4 Esquema general 13

Capítulo 2: Páginas web 14

2.1 Cascading Style Sheet 14

2.2 HyperText Markup Language 16

2.3 JavaScript 17

2.4 React y JSX 19

2.5 CSS-in-JS 21

Capítulo 3: Trabajos relacionados 25

3.1 Herramientas para utilizar CSS-in-JS 25

3.1.1 Styled-Components 25

3.1.2 Styled-JSX 27

3.1.3 Classy 27

3.1.4 React-CSS-Builder 29

3.1.5 React-Theme 30

3.1.6 Glamorous 31

3.1.7 Aphrodite 31

3.2 Criterios de comparación 32

Comparación y conclusiones 33

Capítulo 4: Una herramienta para mejorar la legibilidad de aplicaciones React 37

4.1 Artefactos de Entrada 41

4.1.1 Configuración del transpiler 41

4.1.2 my_component.js 42

4.2 Componentes de proceso 45

(3)

4.2.1.1 Detect Style 45

4.2.1.2 Extract Style 46

4.2.1.3 Create Styled Element 48

4.2.2 PostCSS Post Processing 50

4.3 Artefactos de Salida 51

4.3.1 my_component.js 52

4.3.2 my_component.css 52

Capítulo 5: Caso de Estudio 53

5.1 Experimento 1 53

5.1.1 'Hello World' React 54

5.1.2 Pantalla de acceso 56

5.1.3 Análisis cuantitativo 58

5.1.3.1 Cantidad de líneas de código 58

5.1.3.2 Cantidad de archivos 60

5.1.3.2 Dependencias a otros archivos 61

5.1.3.3 Cantidad de referencias a otros archivos 61

5.2 Experimento 2 62

5.2.1 Preguntas generales 63

5.2.1.1 Años de programación en cualquier lenguaje 63

5.2.1.2 Años de programación en JavaScript utilizando React 65

5.2.2 Preguntas sobre CSS-in-JS 66

5.2.2.1 Conocimiento de existencia de enfoques CSS-in-JS con ejemplo de los

mismos 66

5.2.2.2 Utilización de enfoques CSS-in-JS con ejemplo de los mismos 68

5.2.3 Preguntas sobre la herramienta propuesta 70

5.2.3.1 Legibilidad de fragmento A (tradicional) 71

5.2.3.2 Legibilidad de fragmento B (CSS-in-JS) 72

5.2.3.3 Comparativa de legibilidad entre ambos fragmentos 73

5.2.3.4 Comparativa de estructura de código entre ambos fragmentos 74

(4)

5.2.3.6 Comparativa de facilidad para modificar componentes entre ambos

fragmentos 76

Capítulo 6: Conclusión 77

6.1 Contribuciones 79

6.2 Limitaciones 80

6.3 Trabajos futuros 80

(5)

Índice de figuras

1.1: Esquema general del plugin 11

2.1: Declaración de regla que define el tamaño de la fuente de cualquier elemento H1 14

2.2: Ejemplo simple HTML, estructura simple 17

2.3: Resultado de HTML simple mostrado en Figura 2.2 17

2.4: Elemento simple en React que muestra en pantalla un título 18

2.5: Elemento simple con estado en React que muestra en pantalla un título 20

2.6: Relación entre React, HTML, JS, y CSS para conformar una página web 21

2.7: Mutación de la separación de concerns 22

3.1: Ejemplo simple Styled-Components 26

3.2: Ejemplo simple Styled-JSX 27

3.3: Ejemplo simple Classy 28

3.4: Ejemplo simple React-CSS-Builder 30

3.5: ejemplo simple React-Theme 31

3.6: Ejemplo simple Glamorous 31

3.7: ejemplo simple Aphrodite 32

4.1: Esquema general de la herramienta 40

4.2: Ejemplo básico de configuración del transpiler para proyecto JSX 41

4.3: Ejemplo de archivo JS en el cual se definen dos componentes de manera tradicional 42

4.4: Ejemplo de archivo CSS que provee estilos a los componentes definidos en la Figura 4.3 43

4.5: Ejemplo de archivo JS en el cual se definen dos componentes utilizando la solución propuesta45

4.6: Resultado de extraer los estilos del código en Figura 4.5 47

4.7 : Vinculación de un nuevo nodo al árbol de sintaxis abstracta 48

4.8: Ejemplo de archivo JS resultante de transpiling en el cual se definen dos componentes

utilizando la solución propuesta 49

4.9: Archivo CSS resultante de operar Element (línea 2 de Figura 4.5) 51

4.10: Archivo CSS resultante de operar sobre Foo (línea 36 de Figura 4.5) 51

4.11: Archivo CSS que importa a todos los estilos resultantes 51

5.1: 'Hello World' provisto por create-react-app 54

5.2: Código fuente referido a la Figura 5.1 54

(6)

5.4: Código fuente referido a la Figura 5.3 55

5.5: Pantalla de acceso implementada con enfoque tradicional 56

5.6: Código fuente referido a la Figura 5.5 57

5.7: Pantalla de acceso implementada con el nuevo enfoque 57

5.8: Código fuente referido a la Figura 5.7 58

5.9: Comparativa cantidad de líneas de código ejemplo 'Hello World 59

5.10: Comparativa cantidad de líneas de código ejemplo página de acceso 59

5.11: Comparativa cantidad de archivos ejemplo 'Hello World' 60

5.12: Comparativa cantidad de archivos ejemplo página de acceso 60

5.13: Comparativa cantidad de referencias ejemplo 'Hello World' 60

5.14: Comparativa cantidad de referencias ejemplo 'Hello World' 60

5.15: Cantidad de años de programación, programadores generales 64

5.16: Cantidad de años de programación, programadores especialistas en frontend 64

5.17: Cantidad de años de programación en JavaScript y React, programadores generales 65

5.18: Cantidad de años de programación en JavaScript y React, programadores especialistas en

frontend 65

5.19: Conocimiento de enfoques CSS-in-JS, programadores generales 66

5.20: Enfoques CSS-in-JS conocidos, programadores generales 67

5.21: Conocimiento de enfoques CSS-in-JS, programadores especialistas en frontend 67

5.22: Enfoques CSS-in-JS conocidos, programadores especialistas en frontend 68

5.23: Utilización de enfoques CSS-in-JS, programadores generales 68

5.24: Enfoques CSS-in-JS utilizados, programadores generales 69

5.25: Utilización de enfoques CSS-in-JS, programadores especialistas en frontend 69

5.26: Enfoques CSS-in-JS utilizados, programadores especialistas en frontend 70

5.27: Legibilidad enfoque tradicional, programadores generales 71

5.28: Legibilidad enfoque tradicional, programadores especialistas en frontend 71

5.29: Legibilidad enfoque CSS-in-JS, programadores generales 72

5.30: Legibilidad enfoque CSS-in-JS, programadores especialistas en frontend 72

5.31: Comparativa legibilidad entre enfoques, programadores generales 73

5.32: comparativa legibilidad entre enfoques, programadores especialistas en frontend 73

5.33: Comparativa estructura de código entre enfoques, programadores generales 74

(7)

5.35: Comparativa portabilidad entre enfoques, programadores generales 75

5.36: Comparativa portabilidad entre enfoques, programadores especialistas en frontend 76

5.37: Comparativa de facilidad para modificar componentes,, programadores generales 76

5.38: Comparativa de facilidad para modificar componentes, programadores especialistas en

(8)

Índice de tablas

3.1: Categoría de las herramientas 31

3.2: Disponibilidad de las herramientas y extracción de CSS 32

3.3: Usabilidad de las herramientas 33

(9)

Capítulo 1: Introducción

A medida que las páginas estáticas evolucionaron en aplicaciones web comenzó a cambiar la forma de separación de concerns. En este dominio era importante separar la lógica, el estilo, y la estructura de cada componente [1]. Esta separación se veía marcada por los lenguajes de programación en los cuáles se implementaba cada parte, utilizando HyperText Markup Language (HTML) para la estructura de los componentes, JavaScript para la lógica de los mismos, y finalmente Cascading Style Sheet (CSS) para el estilo deseado en cada uno de ellos.

Al complejizarse las aplicaciones web se comenzó un nuevo flujo de separación de concerns, donde cada componente pasa a diferenciarse entre sí y contiene su propia estructura, lógica, y estilo [7]. La mutación de esta separación de concerns se da al pasar de una enfoque que separaba por comportamiento, estilo, y estructura, siendo independiente de los componentes y guiada por el lenguaje en el cual se programa. A una separación de concerns por componentes, los cuales contienen su propio comportamiento, estilo, y estructura, independientemente del lenguaje en que esté implementada cada característica.

CSS presentó muchos problemas con esta nueva forma de separar los concerns [2][3], ya que en el enfoque tradicional se mantiene un archivo CSS global que contiene los estilos de todos los componentes de la página web. Esta característica se da por el tiempo necesario para cargar múltiples archivos de estilos desde el lado del cliente.

A partir de esto surge el concepto de CSS-in-JS, este nuevo enfoque plantea embeber los estilos dentro del código JavaScript, y a su vez reducir la granularidad de los estilos a nivel componente, resultando en que un mismo archivo contiene la lógica, estructura, y estilo de un componente simple. Esto plantea una nueva forma de pensar las páginas web por parte del desarrollador, y a su vez un nuevo desafío por parte de la comunidad para crear nuevas herramientas que simplifiquen dicho proceso. Además, plantea dejar de mantener extensas declaraciones de CSS globales, esto se da debido a la abstracción del modelo CSS a nivel de componentes en vez de a nivel de documento.

1.1 Desarrollo de páginas web en la actualidad

JavaScript se ha convertido en el lenguaje más usado en el último año, y dentro de JavaScript el framework más utilizado es React . React [6] permite implementar1 componentes que poseen su comportamiento y estructura contenidos en el mismo componente, pero carece de un sistema para contener los estilos de dichos componentes, en este marco es que la integración CSS-in-JS se ve como el proceso natural para finalizar el concepto de componentes web autocontenidos.

(10)

estilo correspondiente. Al programar con React se utiliza una extensión de sintaxis de JavaScript llamada JSX [8]. JSX permite, mediante el uso de tags similares a los que componen HTML [14], describir la estructura del componente involucrado. Esto implica la utilización de Babel[21] para realizar la transformación de este código (JSX) a JavaScript estándar[9]. El archivo CSS posee las clases que deben ser importadas, y luego referenciadas en los elementos de JSX correspondientes, o enlazadas en su debida stylesheet, mientras que en el JS tiene la funcionalidad y estructura del componente.

El resultado del método tradicional al llevar a cabo un proyecto[15] es:

● Una gran cantidad de código CSS dentro de un mismo archivo: mientras la estructura y lógica de cada componente se encuentra en archivos JS correspondientes a cada componente, generando dificultades al modificar un estilo de un componente dado. Incluso guiando al mal uso de clases CSS, por ejemplo, generando conflictos de nombrado (ya que no existe un error al nombrar igual dos estilos, simplemente el último sobreescribe al primero dada la característica de cascada de CSS). Este problema se encuentra acentuado al reutilizar elementos o al añadir nuevos desarrolladores a un equipo. En el caso de reutilizar componentes se debe a que además de aislar la funcionalidad y estructura del componente en cuestión a ser reutilizado, también se debe buscar dentro del archivo CSS (que contiene los estilos de toda la aplicación) las clases necesarias para su correcta visualización. Mientras que en el caso de añadir un nuevo desarrollador el problema subyace en que debe comprender la notación CSS utilizada por el equipo, y además leer todo el código cada vez que desee crear un nuevo componente para evitar duplicar nombres de clases y causar conflictos con componentes ya existentes. En los últimos años se intentó guiar el desarrollo hacia componentes desacoplados con estilos separados por cada uno de ellos. Sin embargo, este enfoque agrega un problema adicional que es la necesidad de configurar sistemas de construcción de paquetes más complejos.

● Cuando se desea reutilizar el componente en otro sistema se deban buscar las clases en el CSS : Esto puede resultar costoso y generar errores. Es importante destacar que también resulta complejo para los desarrolladores referenciar de forma continua una clase CSS en la prop correspondiente de un elemento. Las props son entradas arbitrarias que puede tener un elemento JSX, estas son inyectadas al elemento y son de sólo lectura. A un elemento se le pueden inyectar tantas props como el programador considere necesario mientras no se superponga con alguna prop preestablecida. También, un elemento puede obligar a que ciertas props sean inyectadas para ser instanciado. En adición a esto, es posible el uso de la notación Block Element Modifier (BEM), por lo cual es muy probable que los nombres de las clases CSS sean extensos. El uso de esta notación aumenta la posibilidad de errores tipográficos[16] que rara vez son captados por las herramientas de desarrollo, ya que al referenciar una clase de CSS inexistente simplemente se aplica el estilo correspondiente al elemento padre.

(11)

directamente dichos estilos en el HTML de salida (generalmente utilizando métodos como tablas de estilos globales, o dejándolos inline bajo un tag style), sin generar un archivo CSS por separado. Además, la mayoría de estos enfoques delegan al usuario la responsabilidad del nombrado de las clases CSS y la referencia de las mismas en cada elemento JSX. Es decir, no aportan a evitar los errores tipográficos ni facilitar la escritura para el programador.

El principal de estos problemas es que no den como salida un archivo CSS ya que durante el transpiling se encargan de agregarlo al futuro código HTML que representará la página estática. El transpiling es la transformación de un código de alto nivel (JSX en este caso), a un código con un nivel de abstracción similar (para este transpiling se utiliza Babel, que se encarga de transformar JSX y EcmaScript 6, a JS estándar para que pueda ser interpretado por cualquier navegador). Al no dar como salida código CSS no se le permite al programador experimentado realizarle un procesamiento posterior al código, generando menor flexibilidad a la hora de plantear las etapas de procesado del código previo al despliegue del sistema en los componentes físicos.

1.2 Una herramienta para mejorar la legibilidad de aplicaciones

React

Teniendo en cuenta los problemas descritos anteriormente en este trabajo se propone un enfoque en el cual el programador sólo debe generar un archivo JS, en el cual declara nuevos elementos personalizados a los cuáles se les asocia un estilo definido en un objeto plano. Por lo que el programador no debe llevar control de los nombres de las clases CSS asociadas a cada tag, ni tampoco generar de forma manual el archivo CSS que contendrá los estilos. Además, también se prioriza el dar como resultado un archivo CSS que pueda ser insertado dentro del proceso de producción preexistente en el sistema que se utilice este nuevo enfoque. Este enfoque es materializado mediante la creación de un plugin que se interpone dentro del proceso de transpiling y realiza las mutaciones necesarias para llegar al resultado esperado.

(12)

Figura 1.1: Esquema general del plugin

Los elementos de este trabajo pueden ser divididos en artefactos de entrada, componentes de proceso, y artefactos de salida. Los mismos son:

● Artefactos de entrada:

○ configuración del transpiler: aquí se especifica qué se desea agregar al transpiling estándar de Babel un nuevo plugin, y dentro del plugin el prefijo para cada clase CSS que se genere, la opción del prefijo se da ya que en proyectos de gran tamaño es usual utilizar un prefijo en todas las clases pertenecientes al mismo. Es necesario tener en cuenta que por restricciones de Babel este archivo debe nombrarse .babelrc.

(13)

asociados a estilos que propone este enfoque. Los mismos son variaciones a los tags tradicionales de JSX incluyendo el prefijo ‘STYLED’.

● Componentes de proceso:

○ Transpiling process: en este componente se realiza el proceso de transpiling, el mismo se encuentra dividido en otros tres componentes, que son los que se adicionan al proceso de transpiling tradicional de JSX a JS. Este componente genera un código JS ejecutable en cualquier navegador.

i. Detect style: se encarga de detectar en el árbol sintáctico la declaración de los estilos, esto se realiza mediante la implementación de un visitor sobre los nodos del árbol.

ii. Extract style: una vez detectado el estilo debe ser extraído del árbol, y se debe generar el CSS correspondiente a la descripción encontrada en el objeto plano que se encarga de describir el estilo. En este punto también se realiza la asignación de un nombre para el estilo, el cual luego es asignado en los elementos correspondientes.

iii. Create styled component: se genera un componente estándar con las referencias a las clases CSS necesarias, este componente se inserta en el árbol sintáctico en el lugar del componente personalizado creado por el usuario.

○ PostCSS post processing: aquí sea realiza el formateo de los archivos CSS, productos del transpiling, generando como salida un archivo legible y con una sintaxis estándar.

● Artefactos de salida:

○ my_component.js: es el archivo JS ya procesado con los tag estándar, en este esquema se simplifica su vista al no mostrarlo luego de ser procesado a JS estándar, donde todos los elementos declarados como tags desaparecen y son convertidos en funciones, ya que estos tags son sintaxis correspondiente a JSX.

○ my_component.css: en este archivo se encuentran los estilos correspondientes al componente procesado, habrá un archivo por cada componente en el JS de entrada.

1.3 Caso de estudio

Para poder validar los beneficios del enfoque se realizó un caso de estudio basado en dos experimentos:

● Experimento 1: Implementación una página popular utilizando el enfoque propuesto en este trabajo, y su comparativa con la implementación tradicional. La página a analizar fue el 'Hello World' proporcionado por la herramienta de configuración automática de entorno provista por React. También se analizó una página de acceso tradicional implementada específicamente para este trabajo final.

(14)

de su labores cotidianas), y programadores en general. En la encuesta se corroboró los años de experiencia en programación, y en desarrollo utilizando React de cada sujeto, seguido por su conocimiento de enfoques CSS-in-JS. Finalmente, se realizó una comparativa entre el enfoque propuesto por este trabajo y el enfoque tradicional donde se debía valorar los mismos bajo diversas características.

Estos experimentos corroboraron la efectividad del enfoque. En el primer experimento se verificó que se eliminan las dependencias del componente a archivos externos, y también como derivado de esto se eliminan las referencias de los componentes hacia otros archivos, además también se eliminó completamente la existencia de líneas de código CSS.

En este primer experimento también se verificó el potencial de la herramienta ya que se pudo replicar a la perfección las páginas objetivo sin mayores inconvenientes, acoplando el nuevo proceso de transpiling al proceso por defecto para transformar JSX en JavaScript.

Mientras que en el segundo experimento se logró verificar que un grupo de programadores, tanto especialistas en frontend como novatos en el área, encontró mejor el enfoque propuesto por este trabajo que el enfoque tradicional en cuanto a: legibilidad, estructura de código, portabilidad, y facilidad para modificar componentes.

También en este segundo experimento se pudo apreciar la diferencia entre las valoraciones de los dos grupos de programadores encuestados, consiguiendo respuestas más favorables hacia el enfoque de CSS-in-JS implementado en este trabajo por parte de los programadores con mayor experiencia en el área.

1.4 Esquema general

El esquema general de la tesis está organizado de la siguiente manera:

En el capítulo 2 se presentan los conceptos básicos sobre páginas web y la tecnología detrás de ellas. Además, este capítulo presenta las nociones de React y CSS-in-JS, enfoques modernos para la creación de páginas web.

En el capítulo 3 se describen varios enfoques y herramientas que están relacionados con la inclusión de CSS-in-JS en aplicaciones web. Todos estos enfoques son reportados y comparados.

En el capítulo 4 se presenta el enfoque propuesto en la nueva herramienta. Primero se desarrolla la problemática, artefactos de entrada, salida, y componentes del proceso. Luego se describe detalladamente cada elemento realcionado a la herramienta incluyendo detalles de implementación y diseño.

En el capítulo 5 se presenta el caso de estudio dividido en 2 experimentos junto con sus resultados y análisis.

(15)

Capítulo 2: Páginas web

Las páginas web tienen tres componentes fundamentales que serán analizados en este trabajo: Cascading Style Sheet, JavaScript, y HyperText Markup Language[1]. Formalmente cada uno de los miembros de este conjunto se encarga de una parte distinta pero igual de importante de una aplicación web:

● Cascading Style Sheet: dicta cómo se debe ver cada parte de la aplicación. ● HyperText Markup Language: se encarga de la estructura de los componentes. ● JavaScript: provee comportamiento.

2.1 Cascading Style Sheet

En el año 1994 Håkon Wium Lie propuso por primera vez el concepto de Cascading Style Sheet (CSS), pero no fue hasta el año 2006 que se formalizó dicha propuesta en su tesis doctoral en la Universidad de Oslo [2]. Luego de esto CSS se convirtió en el método utilizado para definir cómo se debe visualizar un documento web. Dicha popularidad se da debido a que puede ser introducido en cualquier tipo de proyectos, y que posee una curva de aprendizaje baja, además de facilitar la separación de concerns.

Un archivo CSS contiene reglas que describen propiedades visuales sobre elementos definidos en la estructura del documento web, los cuales pueden ser referenciados por nombres de clases, identificadores únicos, o estructuras que los componen. Las propiedades a su vez tienen asignado un valor particular definido en diversas unidades, permitiendo así por ejemplo la definición de una regla que afecte a todos los elementos de tipo H1 (Header 1) con un font-size (propiedad que determina el tamaño de fuente) de 25px (nuevo tamaño en pixeles de todos los elementos H1). Esta regla se puede ver en la Figura 2.1.

1. h1 ​{

2. ​font-size​:​ ​25px​;

3. }

Figura 2.1: Declaración de regla que define el tamaño de la fuente de cualquier elemento H1

Es importante tener en cuenta que cualquier regla que sobreescriba una propiedad sobre un elemento será aceptada siempre y cuando esté escrita luego de la primer regla que definía dicha propiedad. Esto se debe al parsing en cascada que realiza el navegador sobre los archivos CSS.

(16)

● Errores tipográficos: los errores de sintaxis producidos por el desarrollador, por ejemplo el escribir mal el nombre de una propiedad, no son tenidos en cuenta ni alertados, simplemente el estilo no se considera válido.

● Declaraciones inválidas: al asignar un valor no válido a una propiedad la misma es ignorada, pero no se emite aviso alguno de una asignación errónea.

● Estructura y organización: por la característica de ser un lenguaje con cascading (esto quiere decir que se interpreta de arriba hacia abajo quedando como valor final el último leído para cada propiedad) es importante la estructura y organización del código, ya que puede conllevar a sobre escribir estilos y realizar cambios colaterales no deseados, como por ejemplo, esperar un valor de 20px en un margen, pero por una regla declarada luego (quizás en un archivo distinto) cambiarlo a 35px.

Un error notado por la comunidad desde un principio es la diferencia de tiempo entre que un cambio es propuesto en el estándar del lenguaje, y su adopción por parte de los navegadores. A partir de esto se plantea como solución a futuro extraer el comportamiento interno a bibliotecas JavaScript que sean inyectadas de forma tradicional.

Este paradigma generó buenos resultados hasta la aparición de las single-page application (SPA), o aplicación de página única [3][10]. SPA es una aplicación web contenida en una sola página con el propósito de dar una experiencia más fluida a los usuarios como una aplicación de escritorio. En un SPA todos los códigos de HTML, JavaScript, y CSS se cargan de una vez al principio de la navegación, o los recursos necesarios se cargan dinámicamente como lo requiera la página y se van agregando normalmente como respuesta de las acciones del usuario. La página no tiene que cargar otra vez en ningún punto del proceso y tampoco se transfiere a otra página. En este momento fue cuando desde la comunidad se detectaron problemas en la escalabilidad del enfoque tradicional para cumplir con la expectativas de los usuarios de sitios más dinámicos, que permitan una mejor experiencia al usuario con animaciones más complejas y mayores detalles visuales. Los principales problemas listados con el objetivo de mejorar el estilo de las páginas desde el punto de vista programático[11]:

● Espacios de nombre globales

● Dependencias

● Eliminación de código muerto

● Minificación

● Constantes compartidas

● Resolución no determinística del valor de propiedades

(17)

Esto llevó a la creación de nuevas soluciones que basándose en CSS generaron un nuevo enfoque nombrado CSS-in-JS[12], este enfoque será abordado posteriormente en este mismo capítulo.

2.2 HyperText Markup Language

HyperText Markup Language (HTML) es un lenguaje de marcado para páginas web que surge en el año 1991 con la idea de crear un sistema de etiquetado que permita identificar distintas estructuras dentro de una página web [4]. Un documento HTML se compone de diversas etiquetas rodeadas por corchetes angulares las cuales describen la estructura de un documento, y pueden incluir o hacer referencia a scripts que dictaminan el comportamiento de dichas estructuras.

Las principales etiquetas utilizadas son:

● div: Es un contenedor en bloque, esto quiere decir que utiliza el 100% del espacio que le provee el padre. Sirve para crear secciones o agrupar contenidos.

● span: Es un contenedor en línea, esto quiere decir que utiliza sólo el espacio necesario, permitiendo a hermanos situarse junto a él. Sirve para aplicar estilo al texto o agrupar elementos en línea.

● h: Seguido por un número demarca un elemento de título y su relevancia, siendo 1 la mayor relevancia, y 6 la menor.

● p: Es un elemento de párrafo. Sirve para denotar que lo que se encuentra en su interior es un párrafo de un texto.

● ul: Contiene una lista, dentro contiene como hijos directos ítems pertenecientes a una misma lista.

● li: Elemento de lista, debe estar contenido por un ul, y ser hermano de otros elementos cuya etiqueta es li.

● a: Elemento que posee un link a otra URL, al ser presionado el navegador intenta cargar dicha URL.

● head: Define la cabecera del documento HTML; dicha cabecera suele contener información sobre el documento que no se muestra directamente al usuario como, por ejemplo, el título de la ventana del navegador.

● body: Define el contenido principal o cuerpo del documento. Esta es la parte del documento html que se muestra en el navegador

Existen más etiquetas de HTML que refieren a cuestiones semánticas específicas, por ejemplo citas, negritas, cursiva, navegaciones, etc. pero a fines prácticos los antes listados son los más populares para desarrollar un sitio web, el resto de las etiquetas añaden semántica interpretada por los buscadores en sus algoritmos de indexación.

(18)

sistema, ya que en el código HTML no se realiza ninguna referencia a un archivo CSS. Este código se supone como hijo de una etiqueta body a renderizar.

Se puede apreciar el carácter de HTML quien tan sólo otorga una estructura a la información que se desea mostrar al usuario, sin acompañarla con ningún tipo de comportamiento o detalles de estilos.

1. <​div​>

2. <​h1​>​Hola​<​/​h1​> 3. <​h2​>​Mundo​<​/​h2​> 4. <​/​div​>

5. <​span​>​hola​<​/​span​> 6. <​span​>​mundo​<​/​span​> 7. <​ul​>

8. <​li​>​item 1​<​/​li​> 9. <​li​>​item 1​<​/​li​> 10. <​li​>​item 1​<​/​li​> 11.<​/​ul​>

Figura 2.2: Ejemplo simple HTML, estructura simple

Figura 2.3: Resultado de HTML simple mostrado en Figura 2.2

2.3 JavaScript

JavaScript (JS) es un lenguaje de programación interpretado, dialecto del estándar ECMAScript. Se define como orientado a objetos, basado en prototipos, imperativo, débilmente tipado y dinámico[5].

(19)

● Cargar nuevo contenido para la página o enviar datos al servidor a través de AJAX sin necesidad de recargar la página (por ejemplo, una red social puede permitir al usuario enviar actualizaciones de estado sin salir de la página).

● Animar los elementos de las páginas, hacerlos desaparecer, cambiar su tamaño, moverlos, etc.

● Validar de los valores de entrada de un formulario web para asegurarse de que son aceptables antes de ser enviados al servidor.

● Transmitir información sobre los hábitos de lectura de los usuarios y las actividades de navegación a varios sitios web. Las páginas Web con frecuencia lo hacen para hacer análisis web, seguimiento de anuncios, la personalización o para otros fines.

Dado que el código JavaScript puede ejecutarse localmente en el navegador del usuario (en lugar de en un servidor remoto), el navegador puede responder a las acciones del usuario con rapidez, haciendo una aplicación más sensible. Por otra parte, el código JavaScript puede detectar acciones de los usuarios que HTML por sí sola no puede, como pulsaciones de teclado. Las aplicaciones usualmente se aprovechan de esto al dejar la mayor parte de la lógica de la interfaz de usuario escrita en JavaScript, enviando sólo peticiones específicas al servidor (por ejemplo, el contenido de un mensaje en un servicio de mensajería).

Un motor de JavaScript (también conocido como intérprete de JavaScript o implementación JavaScript) es un intérprete que interpreta el código fuente de JavaScript y ejecuta la secuencia de comandos en consecuencia. El primer motor de JavaScript fue creado por Brendan Eich en Netscape Communications Corporation, para el navegador web Netscape Navigator. El motor, denominado SpiderMonkey, está implementado en C. Desde entonces, ha sido actualizado (en JavaScript 1.5) para cumplir con el ECMA-262 edición 3. El motor Rhino es una implementación de JavaScript en Java. Rhino, como SpiderMonkey, es compatible con el ECMA-262 edición 3. En la actualidad se utiliza V8, un motor de código abierto escrito en C++ para JavaScript creado por Google.

Un navegador web es el entorno de acogida más común para JavaScript. Los navegadores web suelen crear objetos no nativos, dependientes del entorno de ejecución, para representar el Document Object Model (DOM) en JavaScript. El servidor web es otro entorno común de servicios. Un servidor web JavaScript suele exponer sus propios objetos para representar objetos de petición y respuesta HTTP, que un programa JavaScript podría entonces interrogar y manipular para generar dinámicamente páginas web.

(20)

2.4 React y JSX

Antes de 2013 el paradigma favorito a la hora de desarrollar en JavaScript era el binding de dos caminos, esto significaba que los eventos en la vista accionaban actualizaciones en el modelo y que los eventos en el modelo generaban actualizaciones en la vista. Este enfoque causaba bajo rendimiento[17], además de dificultar la depuración ya que realizar un seguimiento de qué evento causó cada actualización era una tarea no trivial. Además, en esta época comenzó el surgimiento de las Single Page Application[10], lo cual significaba que el usuario permanecería más tiempo en un mismo contexto, por lo que tomó mayor relevancia la arquitectura de la aplicación y el manejo de los estados de la misma.

En el año 2013 React fue lanzado al mercado, y adoptado rápidamente por la comunidad principalmente por su sencilla API, sólo contaba con un método llamado render[6]. Además contaba con otras grande innovaciones, como una interfaz declarativa, Donde los componentes son funciones idempotentes (esto quiere decir que la composición de las mismas no afectará el resultado final), y soporta el renderizado en cliente y servidor, también vale la pena aclarar que es tan solo código JavaScript, sin ningún tipo de lenguaje de dominio específico.

Otro factor que jugó un rol importante en el posicionamiento de React ante la comunidad fue la creación de nuevos frameworks y su fácil acoplamiento a React, quizás el más conocido es Redux[6] quien provee una implementación del patrón de flujo de datos Flux[18]. El mismo se basa en la existencia de un estado central inmutable común a todos los componentes, y los componentes realizan llamados a acciones para proponer una transición de estado, y reciben los cambios como mutaciones en sus propiedades heredadas. Este sistema de flujo de datos organiza de una forma eficiente la aplicación y además provée una evolución natural para crear SPAs[10].

Otro cambio importante implementado por React es la eficiencia en el renderizado, normalmente un proceso de renderizado se desencadena ante un cambio en el DOM y consume gran cantidad de tiempo, la secuencia de paso a gran escala sería:

1. Parsear y ejecutar el código JavaScript

2. Realizar cálculos de valores CSS

3. Generar el layout

4. Pintar la pantalla

5. Componer las capas

(21)

algoritmo que denota las diferencias entre el virtual DOM y el DOM real, dando como resultado la modificación del DOM tan solo en los nodos necesarios.

Desde el grupo de desarrolladores de React[6] llegaron a la conclusión que la lógica de renderizado está inherentemente acoplada con otra lógica dentro de la interfaz del usuario, ya sea por cómo son manejados los eventos, cómo cambia el estado en el tiempo, y cómo la información es preparada para su visualización. Por lo tanto, en vez de separar las tecnologías dejando la lógica y la estructura de la aplicación en archivos separados se decidió separar por concerns en componentes débilmente acoplados entre sí que contienen tanto la lógica como la estructura.

Así es como nace JSX[14], que es simplemente una extensión de sintaxis para describir cómo un componente debe verse desde el punto de vista de interfaz de usuario, JSX es semejante a un lenguaje de template pero hay que tener en cuenta que posee todo el poder de JavaScript, ya que es tan solo una forma distinta de describir las funciones de creación de componentes en React, luego del transpiling desaparecen los tags creados y sólo quedan funciones de creación de elementos. Por ejemplo, en la Figura 2.4 se puede ver un ejemplo simple de un elemento que renderiza un texto estático en pantalla dentro de un elemento H1 de HTML.

1. const​ Element ​=​ (props) => ​<​h1​>​Hola mundo​!</​h1​>;

Figura 2.4: Elemento simple en React que muestra en pantalla un título

Además de estos elementos simples también existen elementos más complejos que poseen estado propio y diversos puntos de anclaje donde se pueden asociar acciones. Estos puntos de anclaje son: al montar el componente, luego de montar el componente y al actualizar alguna propiedad del componente. Un ejemplo simple de este tipo de componente se puede ver en la Figura 2.5, donde se renderiza un elemento igual al de la Figura 2.4 pero con la particularidad que luego de ser montado en la página emite una alerta por consola dándo a conocer que fue montado, y que el texto es requerido del estado. La importancia de mantener un estado es que en cada modificación del mismo por medio del método setState() provisto por React se realizará una nueva renderización del elemento y de todos sus hijos, permitiendo de esta manera visualizar en tiempo real los cambios producidos a través de eventos JavaScript.

1. class​ Element ​extends​ React.​Component​ ​{ 2. state ​=​ ​{

3. text​:​'Hola Mundo!'

4. ​}

5. componentDidMount​(){ 6. console.​log​(​'mounted'​)​; 7. ​}

8. render​(){

9. ​return​(

10. ​<​h1​>​{​this​.​state​.​text​}​</​h1​>

(22)

Figura 2.5: Elemento simple con estado en React que muestra en pantalla un título

Para el transpiling se utiliza Babel[21], que es un transpiler (esto quiere decir que dado un input de código de alto nivel, en este caso JSX, lo transforma en código de alto nivel, en este caso JavaScript) popular en la comunidad. Babel se encarga además de realizar la transformación del código JavaScript y JSX del desarrollador a un estándar aceptado por el navegador objetivo. Debido a que hoy en día todavía se encuentran vigente diversas versiones de JavaScript y no todas son soportadas por todos los navegadores, normalmente se reduce el código a EcmaScript 5[19] que es aceptado por todos los navegadores populares, aunque los desarrolladores normalmente trabajan con EcmaScript 7[20].

En la Figura 2.6 se puede ver como entre todas las partes conforman una página web (React, HTML, CSS, y JS), siendo React quien define la estructura y el comportamiento, esto luego es traducido internamente a HTML y JS. Mientras que CSS define el estilo de la página, como se puede ver CSS se encuentra aislado de React.

Figura 2.6: Relación entre React, HTML, JS, y CSS para conformar una página web

2.5 CSS-in-JS

(23)

estilo, y la estructura de cada componente. Esta separación se veía marcada por los lenguajes de programación en los cuáles se implementaba cada parte, utilizando HyperText Markup Language (HTML) para la estructura de los componentes, JavaScript para la lógica de los mismos, y finalmente Cascading Style Sheet (CSS) para el estilo deseado en cada uno de ellos.

Al complejizarse las aplicaciones web se comenzó un nuevo flujo de separación de concerns (Figura 2.7)[12], donde cada componente pasa a diferenciarse entre sí y contiene su propia estructura, lógica, y estilo. La mutación de esta separación de concerns se da al pasar de un enfoque que separaba por: comportamiento, estilo, y estructura, siendo independiente de los componentes y guiada por el lenguaje en el cual se programa (Figura 2.7, izquierda), a una separación por cada componente que contiene su propio comportamiento, estilo, y estructura (Figura 2.7, derecha), independientemente del lenguaje en que esté implementada cada característica.

Figura 2.7: Mutación de la separación de concerns

CSS presentó muchos problemas[22] con esta nueva forma de separar los concerns, ya que en el enfoque tradicional se mantiene un archivo CSS global que contiene los estilos de todos los componentes de la página web. Esta característica se da por el tiempo necesario para cargar múltiples archivos de estilos desde el lado del cliente.

(24)

Existen grandes diferencias entre CSS-in-JS y simplemente insertar estilos a los componentes. La principal diferencia entre estos dos métodos es la referencia a los estilos, cuando se inserta un estilo a un nodo de forma directa este estilo está asociado al mismo dentro del DOM, mientras que utilizando CSS-in-JS el estilo se insertará en el cabezal del documento y será referenciado a través de un nombre de clase. Esto es muy importante ya que permite utilizar libremente CSS, mientras que la inserción directa en el nodo limita por ejemplo el uso de ciertos pseudoselectores. Los pseudoselectores son puntos de anclaje que permiten modificar el estilo ante ciertos comportamientos habituales, como por ejemplo: :disabled, :before, :nth-child. Esto se debe a que el código CSS es generado a diferencia de la inserción directa.

Otra de las características de CSS-in-JS es el mantener el estilo del componente en el mismo archivo que su lógica y estructura. Esto permite crear componentes autocontenidos (se puede encontrar en un mismo archivo la estructura, el estilo, y el comportamiento de un componente), lo cual mejora la reutilización de código ya que para extraer un componente de un proyecto no se debe buscar cada uno de sus estilos en un extenso archivo global.

Los principales beneficios de CSS-in-JS son:

● Permite no tener que mantener grandes bibliotecas de estilos al abstraer CSS a nivel de componentes.

● Cuenta con todo el potencial del ecosistema de JavaScript para así poder mejorar el código CSS.

● Posee reglas de aislamiento, generalmente los selectores de ámbito no son suficiente para aislar componentes, CSS por defecto hereda ciertas reglas del componente padre a menos que se especifique lo contrario (lo cual puede guiar a problemas), utilizando simple JavaScript se puede lograr que un componente no herede ninguna propiedad, permitiendo que cada componente esté aislado sin recibir más reglas que las definidas en el mismo.

● Provee creación de ámbitos, debido a que CSS sólo posee un espacio de nombres global, es difícil evitar colisiones entre selectores dentro de aplicaciones no triviales, esto quiere decir que más de un nombre de clase sea igual. Cuando sucede una colisión se aplica a todos los elementos sólo la última clase definida. Aunque se puede evitar colisiones utilizando convenciones de nombres dentro del proyecto, esto no provee seguridad alguna ante la integración de código externo a nuestro proyecto, utilizando JavaScript se pueden generar nombres de clase únicos.

● Añade prefijos de acuerdo al navegador, estos prefijos permiten determinar características de cada navegador, las distintas reglas CSS son aplicadas bajo distintos nombres diferenciadas por un prefijo en los navegadores comerciales más populares. Esto se puede automatizar fácilmente durante la transformación a CSS.

(25)

● Elimina código muerto a través de podas dentro de los sistemas de construcción como Webpack[32].

(26)

Capítulo 3: Trabajos relacionados

Para incluir el estilo de los componentes dentro de la declaración de los mismos existen diversos enfoques, los dos más populares son: interferir en el proceso de transpiling [13] (proceso que tiene como entrada código en un lenguaje de programación, y su salida es el mismo código pero en otro lenguaje de programación de similar nivel de abstracción) desde JSX (extensión de sintaxis a JavaScript propuesta para la programación utilizando React) a JavaScript. O añadir funciones que realicen la inyección de de estilos propios en el DOM (Document Object Model, este objeto permite a los programas modificar elementos en archivos HTML de manera estándar, en este caso se modifica el archivo HTML que luego es mostrado en el navegador al usuario).

● Interferir el proceso de transpiling: este enfoque requiere modificar las configuraciones de Babel (el transpiler utilizado para que dado un código en JSX la salida sea código JS), la particularidad de este método es que al programador se le presenta como una extensión de sintaxis, donde debe aprender las palabras claves y estructuras para poder añadir los estilos en cada componente, la principal herramienta que utiliza esta técnica es Styled-JSX.

● Añadir funciones que inyecten los estilos: este enfoque requiere que en cada ocasión que se desee utilizar un estilo dentro de un componente se debe importar en dicho archivo la función que se encargará de insertar luego el estilo en el DOM. Esta técnica requiere que el programador conozca la API de la herramienta a utilizar, para saber qué función es necesaria importar en cada situación, la herramienta más popular bajo este concepto es Styled-Components.

Las implementaciones de ambas técnicas poseen la falencia que finalizan inyectando de forma inline el estilo dentro del DOM, sin dar lugar a un post-procesamiento dentro de un ciclo formal estándar para la construcción de sitios.

3.1 Herramientas para utilizar CSS-in-JS

Actualmente se utilizan principalmente dos herramientas a nivel empresarial, Styled-JSX y Styled-Components, ambas tienen un enfoque de trabajo distinto. De todas maneras se analizarán otras herramientas con cierto grado de impacto en la comunidad.

3.1.1 Styled-Components

La herramienta Styled-Components[23] utiliza el enfoque de añadir funciones para inyectar luego los estilos en el DOM, además también cuenta con otra ventaja que es la creación de estilos dinámicos, y que reside en la herramienta la generación del nombre para cada clase CSS. Quitando al usuario la tarea de referenciar cada componente visual con una clase CSS.

(27)

conocidos como props). Esta particularidad fue introducida por Styled-Components que logro una optimización aceptable al realizar la tarea de generación de estilos de forma dinámica, algo que anteriormente generó problemas en múltiples proyectos de esta índole.

En la Figura 3.1 se puede ver un ejemplo simple donde se crean dos componentes, uno llamado Title (Figura 3.1, línea 6), y otro llamado Wrapper (Figura 3.1, línea 13). A partir de la definición de ambos se pueden utilizar como si fuesen tags personalizados de JSX, donde cada uno a su vez tiene asociado un estilo, sin la necesidad de tener que realizar una referencia explícita a una clase de CSS.

1. import​ React from ​'react'​;

2. //la función styled es importada, lo cual genera un ancla para styled-components, sabiendo que en este archivo todo lo que siga luego de dicha palabra clave será generación de estilos

3. import​ styled from ​'styled-components'​;

4.

5. // Crea un componente react llamado <Title> que renderiza dentro de sí un <h1> que está alineado en el centro de la pantalla, su tamaño es un 50% más grande que el tamaño seteado en el cuerpo de la página, y cuyo color es palevioletred

6. const​ Title ​=​ styled.​h1​`

7. font​-​size​:​ 1.5em​; 8. text​-​align​:​ center​;

9. color​:​ palevioletred​;

10.`​;

11.

12.// Crea un componente llamado <Wrapper> que renderiza dentro de sí un <section> que cuenta con padding en todas las direcciones y un fondo color papayawhip

13.const​ Wrapper ​=​ styled.​section​`

14. padding​:​ 4em​;

15. background​:​ papayawhip​;

16.`​;

17. ...

18.// Luego se utilizan como cualquier otro componente de react, sólo que tienen estilos asociados

19.<​Wrapper​>

20. ​<​Title​>​Hola mundo!​</​Title​>

21.</​Wrapper​>

Figura 3.1: Ejemplo simple Styled-Components

(28)

3.1.2 Styled-JSX

La herramienta Styled-JSX[24] utiliza el enfoque de interferir en el proceso de transpiling para inyectar los estilos inline a partir de referencias creadas por el programador. A diferencia de Styled-Components, desde esta herramienta se deja la responsabilidad del nombrado de las clases CSS al programador, esto quiere decir que el programador es el responsable de asignar un nombre a cada clase CSS para luego ser referenciada por el mismo.

También cuenta con un concepto de ámbitos, dónde un estilo definido en un ámbito sólo puede afectar a sus hermanos y los hijos de sus hermanos (en el ejemplo de la Figura 3.2 los estilos sólo aplican a los elementos dentro del React.Fragment declarado en la línea 3). De esta forma se evitan errores comunes como por ejemplo el afectar desde dos lugares a un mismo objeto por un nombre repetido de clases CSS, para permitir esta funcionalidad se genera un hash por cada ámbito que es concatenado al nombre asignado por el programador durante el transpiling.

1. import​ React from ​'react'​;

2.

3. <​React.​Fragment​>

4. ​<​section className​=​"wrapper"​>​ ​//se le asigna la clase wrapper al componente section

5. ​<​h1 className​=​"title"​>​Hola mundo​!</​h1​> ​//se le asigna la clase title al

componente h1

6. ​</​section​>

7. //dentro del tag style se especifican los estilos, la prop jsx sirve como ancla para identificar durante el transpiling

8. ​<​style jsx​>​{​` 9. .​title​ ​{

10. font​-​size​:​ 1.5em​; 11. text​-​align​:​ center​; 12. color​:​ palevioletred​; 13. ​}

14. .​wrapper​ ​{ 15. padding​:​ 4em​;

16. background​:​ papayawhip​; 17. ​}

18. `​}

19. ​</​style​>

20.</​React.​Fragment​>

Figura 3.2: Ejemplo simple Styled-JSX

3.1.3 Classy

(29)

quiere decir que el programador es el responsable de asignar un nombre a cada clase CSS para luego ser referenciada por el mismo.

Para utilizar Classy se debe decorar el componente como primer paso (Figura 3.3, línea 6), luego se define una propiedad style que debe ser static (este modificador permite que la misma propiedad es común a todas las instancias de dicha clase) y en la misma se asigna una cadena de caracteres con el código CSS deseado (Figura 3.3, línea 9). Finalmente en el método render se describe la estructura del componente y se realizan las referencias correspondientes a las clases CSS.

Otra característica de este enfoque es que permite estilos asíncronos definidos en promesas, esto quiere decir que la inyección del estilo puede el programador decidir si realizarla de forma secuencial al cargar el componente, o enviarla a una cola de espera y que su procesamiento sea realizado en un futuro. Esto permite realizar cambio de temas (por ejemplo de una página con colores claros, a una página con colores oscuros) de forma simple, ya que es simplemente encolar una acción que cambie el estilo sobre un evento onClick.

1. import​ React from ​'react'​;

2. // Importar Classy

3. import​ Classy from ​'react-classy'​;

4.

5. // Decorar el componente 6. @​Classy

7. class​ Example ​extends​ React.​Component​ ​{ 8. ​// Agregar estilos CSS

9. ​static​ style ​=​ `

10. .​title​ ​{

11. font​-​size​:​ 1.5em​;

12. text​-​align​:​ center​;

13. color​:​ palevioletred​;

14. ​}

15. .​wrapper​ ​{ 16. padding​:​ 4em​;

17. background​:​ papayawhip​; 18. ​}

19. `

20. render​()​ ​{

21. ​return​ ​(

22. ​<​section className​=​"wrapper"​> ​//se le asigna la clase wrapper al componente

section

23. ​<​h1 className​=​"title"​>​Hola mundo​!</​h1​> ​//se le asigna la clase title al

componente h1 24. ​</​section​>

25. ​)​; 26. ​} 27.}

(30)

3.1.4 React-CSS-Builder

La herramienta React-CSS-Builder[27] utiliza el enfoque de añadir funciones para inyectar luego los estilos en el DOM, esto lo logra manteniendo en memoria un objeto que posee las propiedades CSS asociadas a cada estilo y luego descomponiéndolo y aplicando dichos estilos en cada componente. Al igual que Styled-JSX deja al la responsabilidad de referenciar el estilo al programador, esto quiere decir que el programador es el responsable de asignar un nombre a cada estilo en este caso para luego ser referenciada por el mismo.

Para utilizar React-CSS-Builder primero debemos importar un objeto que expone por defecto dicho paquete (Figura 3.4, línea 3). Luego se define un objeto constante que contendrá nuestros estilos (Figura 3.4, línea 6), a este objeto se le asigna el retorno de la función create. Esta función recibe como parámetro un objeto que contiene una lista de objetos con la característica, el valor de estos elementos de la lista será otro objeto conteniendo las propiedades CSS deseadas con sus valores, mientras que la clave será el nombre que se utilizará para poder referenciarlos a la hora de ser aplicados.

Finalmente se asignan los estilos previamente detallados dentro de la propiedad style de los elementos llamando a la función css del objeto previamente declarado con los estilos. Esta función espera como primer parámetro un string que coincida con alguna clave asociada a un estilo, esto lo que realiza es una asignación inline del estilo, a diferencia de los enfoques analizados previamente React-CSS-Builder embebe los estilos inline dentro del componente, y no en una hoja de estilos referenciada desde el componente.

Una de las principales desventajas de este enfoque es que realiza duplicación de código enviado al cliente, ya que si un estilo es referenciado más de una vez se inyecta el código la cantidad de veces necesarias y no una referencia a un estilo global como en las herramientas analizadas previamente.

1. import​ React from ​'react'​; 2. //importar React-CSS-Builder

3. import​ ReactCSSBuilder from ​'react-css-builder'​; 4.

5. //crear una constante que mantenga los estilos

6. const​ styles ​=​ ReactCSSBuilder.​create​({

7. title ​{

8. fontSize​:​ ​'1.5em'​, 9. textAlign​:​ ​'center'​, 10. color​:​ ​'palevioletred'

11. ​},

12. wrapper ​{

13. padding​:​ ​'4em'​,

14. background​:​ ​'papayawhip'

15. ​} 16.})​; 17.

18.const​ Component ​=​ ​()​ ​=>​ ​(

19. ​<​section style​=​{​styles.css​ ​(​'wrapper'​)}​> ​//se le asigna el estilo wrapper al componente section

(31)

21. ​</​section​> 22.)

Figura 3.4: Ejemplo simple React-CSS-Builder

3.1.5 React-Theme

La herramienta React-Theme[28] utiliza el enfoque de añadir funciones para inyectar luego los estilos en el DOM, esto lo logra manteniendo en memoria un objeto que posee las propiedades CSS asociadas a cada estilo y luego descomponiéndolo y aplicando dichos estilos en cada componente. Al igual que Styled-JSX deja la responsabilidad de referenciar el estilo al programador, esto quiere decir que el programador es el responsable de asignar un nombre a cada estilo en este caso para luego ser referenciada por el mismo.

Primero se debe importar el objeto Theme (Figura 3.5, línea 3), y crear una nueva instancia del mismo (Figura 3.5, línea 6). Luego se debe asociar distintos estilos a este tema, esto se hace por medio de la función setSource (Figura 3.5, línea 9 y línea 16), esta función espera como primer parámetro un string con el nombre por el cual se referenciará el estilo, y como segundo parámetro una función que retorne un objeto que contenga las propiedades CSS a asignar.

Finalmente, utilizando la función getStyle (Figura 3.5, línea 23 y línea 24) se inyectan los estilos dentro de cada componente mediante la propiedad style, esto al igual que en React-CSS-Builder acarrea el problema de duplicación de estilos entre diversas instancias.

1. import​ React from ​'react'​;

2. //importar React-Theme

3. import​ Theme from ​'react-theme'​;

4.

5. //inicializar nuevo tema

6. const​ theme ​=​ ​new​ Theme​()

7.

8. //añadir estilos al objeto Theme 9. theme.​setSource​(​'title',​ ​ ​()​ ​=>​ ​({ 10. fontSize​:​ ​'1.5em'​,

11. textAlign​:​ ​'center'​,

12. color​:​ ​'palevioletred'

13. ​}) 14.) 15.

16.theme.​setSource​(​'wrapper',​ ​ ​()​ ​=>​ ​({ 17. padding​:​ ​'4em'​,

18. background​:​ ​'papayawhip'

19. ​}) 20.) 21.

22.const​ Component ​=​ ​()​ ​=>​ ​(

23. ​<​section style​=​{​theme.​getStyle​(​'wrapper'​)}​> ​//se le asigna el estilo wrapper al componente section

24. ​<​h1 style​=​{​theme.​getStyle​(​'title'​)}​>​Hola mundo​!</​h1​> ​//se le asigna el estilo

(32)

26.)

Figura 3.5: Ejemplo simple React-Theme

3.1.6 Glamorous

La herramienta Glamorous[29] utiliza el enfoque de añadir funciones para inyectar luego los estilos en el DOM, además también cuenta con la ventaja que reside en la herramienta la generación del nombre para cada clase CSS. Quitando al usuario la tarea de referenciar cada componente visual con una clase CSS.

Para su funcionamiento primero se debe importar (Figura 3.6, línea 3), y luego se declaran constantes que pasarán a tomar el lugar de tags JSX con un estilo relacionado. Cada tag se define llamando a una función homónima al tag JSX que se desea utilizar como base (Figura 3.6, línea 6 y línea 11). Finalmente cada tag ocupa su lugar en la estructura del componente, liberando al programador de realizar referencias entre estilo y estructura.

Otro punto a tener en cuenta es que utiliza una sintaxis de objetos para los estilos, lo cual facilita la utilización de variables JavaScript para determinar los valores de los mismos, dando cierto dinamismo y mayor facilidad al programador a la hora de, por ejemplo, plantear estilos que se apliquen de distinta forma de acuerdo a una condición.

1. import​ React from ​‘react’​;

2. //importar glamorous

3. import​ glamorous from ​‘glamorous’​;

4.

5. //crear nuevos tags con estilos asociados que sean equivalentes a un tag ya existente

6. const​ Wrapper ​=​ glamorous​.section​({

7. padding​:​ ​‘4em’​,

8. background: ​‘papayawhip’

9. }) 10.

11.const​ Title ​=​ glamorous.​h1​({

12. fontSize​:​ ​‘1.5em’​,

13. textAlign: ​‘center’​,

14. color: ​‘palevioletred’

15.}) 16.

17.//utilizar los nuevos tags en el componente

18.const​ Component ​=​ ​()​ ​=>​ ​(

19. ​<​Wrapper​>

20. ​<​Title​>​Hola mundo​!</​Title​>

21. ​</​Wrapper​>

22.)

Figura 3.6: Ejemplo simple Glamorous

3.1.7 Aphrodite

(33)

quiere decir que el programador es el responsable de asignar un nombre a cada clase CSS para luego ser referenciada por el mismo.

Ante todo se debe importar ciertas funciones de Aphrodite (Figura 3.7, línea 3), luego se asigna a una constante el retorno de la función create perteneciente a StyleSheet (Figura 3.7, línea 6). Esta función espera como parámetro una lista de objetos, cuyo valor es otro objeto con propiedades CSS, y su clave el nombre de la clase.

Finalmente, en la estructura del componente se asigna como nombre de clase el retorno de la función css enviando como parámetro el campo asociado al estilo deseado de nuestra constante con los estilos asociados.

1. import​ React from ​'react'​;

2. //importar Aphrodite

3. import​ ​{​StyleSheet​,​ css​}​ from ​'aphrodite'​;

4.

5. //crear una constante que mantenga los estilos

6. const​ styles ​=​ StyleSheet.​create​({

7. title ​{

8. fontSize​:​ ​'1.5em'​,

9. textAlign​:​ ​'center'​,

10. color​:​ ​'palevioletred'

11. ​}​, 12. wrapper ​{

13. padding​:​ ​'4em'​,

14. background​:​ ​'papayawhip'

15. ​} 16.})​; 17.

18.const​ Component ​=​ ​()​ ​=>​ ​(

19. ​<​section className​=​{​css​(​styles.​wrapper​)}​> ​//se le asigna la clase wrapper al componente section

20. ​<​h1 className​=​{​css​(​styles.​title​)}​>​Hola mundo​!</​h1​> ​//se le asigna la clase title

al componente h1

21. ​</​section​>

22.)

Figura 3.7: ejemplo simple Aphrodite

3.2 Criterios de comparación

En esta sección se definen los criterios para realizar la comparación entre las distintas herramientas analizadas en la sección 3.1 para la inclusión del CSS en JS.

● Categoría de la herramienta: se categoriza cada herramienta según el enfoque para la inserción del CSS que implementa, los distintos enfoques son listados al comienzo del capítulo 3.

(34)

○ Disponibilidad: hace referencia a si la herramienta está disponible para su uso y si es open source.

○ Interacción del desarrollador: hace referencia a si la herramienta necesita del desarrollador para realizar la vinculación entre cada elemento y su estilo en cada instanciación del mismo.

○ Necesidad de importar funcionalidad: hace referencia a si la herramienta necesita que se realice un import de módulos específicos en cada archivo para su correcto funcionamiento.

○ Entorno de desarrollo: hace referencia a si la herramienta impone alguna limitación al desarrollador en el entorno de desarrollo si desea utilizarla.

○ Facilidad en la búsqueda de errores: hace referencia a si la herramienta genera una salida legible fácilmente para un desarrollador en busca de errores.

○ Extracción de CSS: se refiere a poder extraer los estilos en archivos CSS separados, esto permite una fácil adhesión a un ciclo de vida de software y da la posibilidad a programadores avanzados de realizar optimizaciones posteriores sobre dicho código.

Comparación y conclusiones

En la Tabla 3.1 se muestra cada categoría y el enfoque en el cuál se basan. Mientras que la mayoría de las herramientas añaden funciones que inyectan los estilos, Styled-JSX interfiere el proceso de transpiling, pero todas ellas insertan el nuevo estilo inline dentro del DOM. Esto trae como consecuencia que no se permite la extracción del código CSS para un posterior procesado por parte del programador (Tabla 3.2).

Herramienta Enfoque Sección

Styled-Components Añade funciones, inserta inline

3.1.1

Styled-JSX Interfiere transpiling, inserta inline

3.1.2

Classy Añade funciones, inserta

inline

3.1.3

React-CSS-Builder Añade funciones, inserta inline

(35)

React-Theme Añade funciones, inserta inline

3.1.5

Glamorous Añade funciones, inserta

inline

3.1.6

Aphrodite Añade funciones, inserta

inline

3.1.7

Tabla 3.1: Categoría de las herramientas

En cuanto a disponibilidad de las herramientas, todas ellas son de código abierto y se pueden analizar y extender libremente (Tabla 3.2). Otro punto importante es que gran parte de ellas cuentan con una comunidad activa, principalmente Styled-JSX ya que es desarrollada por Zeit, compañía líder en frameworks de server-side rendering.

Herramienta Disponibilidad Extracción de

CSS

Styled-Components Herramienta open source y disponible via manager de paquetes de NodeJS.

No

Styled-JSX Herramienta open source y disponible via manager de paquetes de NodeJS.

No

Classy Herramienta open source y disponible via manager de paquetes de NodeJS.

No

React-CSS-Builder Herramienta open source y disponible via manager de paquetes de NodeJS.

No

React-Theme Herramienta open source y disponible via manager de paquetes de NodeJS.

No

Glamorous Herramienta open source y disponible via manager de paquetes de NodeJS.

No

Aphrodite Herramienta open source y disponible via manager de paquetes de NodeJS.

No

(36)

Por último en la tabla 3.3 se encuentran criterios orientados a la usabilidad de las herramientas, ya que ambas herramientas lo que buscan es simplificar el trabajo de los desarrolladores web.

Herramienta Interacción con el desarrollador Necesidad de importar funcionalidad Entorno de desarrollo Dificultad en depuración

Styled-Components Genera nombres

de clases

automáticamente

Sí Cualquiera Alta

Styled-JSX Desarrollador debe nombrar las clases y relacionarlas

No Atado a React Normal

Classy Desarrollador

debe nombrar las clases y relacionarlas

Sí Atado a React Normal

React-CSS-Builder Desarrollador debe nombrar los estilos y relacionarlos

Sí Atado a React Alta

React-Theme Desarrollador debe nombrar los estilos y relacionarlos

Sí Atado a React Alta

Glamorous Genera nombres

de clases

automáticamente

Sí Cualquiera Alta

Aphrodite Desarrollador debe nombrar las clases y relacionarlas

Sí Cualquiera Normal

Tabla 3.3: Usabilidad de las herramientas

(37)

funciones propias para su funcionamiento, lo cual genera un efecto negativo en la performance. También dada su generación automática de nombres de clases CSS el depurar es una tarea extremadamente tediosa ya que los nombres son códigos de hash sin relación semántica con los objetos.

En cuanto a React-Theme y React-CSS-Builder se encuentran con alta dificultad para depurar pese a que el programador provee los nombres de los estilos, y también realiza las referencias de forma explícita porque en el código generado el estilo se ve inyectado directamente en el componente, lo que genera ofuscación en el mismo.

Por su parte, Styled-JSX no necesita importar funcionalidad pero se encuentra atada al proceso de transpiling de React. Si se desea utilizar en un proyecto en Angular esto no es posible, debido a la semántica de ámbitos hermanos. En lo que demuestra una diferencia importante con la otra herramienta es en que deja como responsabilidad del programador la generación de nombres de clases CSS, y luego toma estos nombres concatenando un código de hash, lo cual resulta en una depuración más sencilla. También permite la creación de estilos complejos ejerciendo múltiples clases sobre un mismo elemento.

(38)

Capítulo 4: Una herramienta para mejorar la

legibilidad de aplicaciones React

Hoy en día para desarrollar un componente utilizando el framework React es necesario implementar un archivo JavaScript (JS) con la descripción del mismo, y un archivo CSS con el estilo correspondiente. También se debe recordar que al programar con React se utiliza una extensión de sintaxis de JavaScript llamada JSX. JSX permite, mediante el uso de tags similares a los que componen HTML, describir cómo se debe ver el componente involucrado una vez renderizado. Esto implica la utilización de Babel para realizar la transformación de este código (JSX) a JavaScript estándar. El archivo CSS posee las clases que deben ser importadas, y luego referenciadas en los elementos de JSX correspondientes, o enlazadas en su debida stylesheet, mientras que en el JS tiene la funcionalidad y estructura del componente.

El resultado del método tradicional al llevar a cabo un proyecto es:

● Una gran cantidad de código CSS englobado dentro de un mismo archivo, y luego la estructura y lógica de cada componente en archivos JS particulares, generando problemas al modificar un estilo de un componente dado. Incluso guiando al mal uso de clases CSS, por ejemplo generando conflictos de nombrado (ya que no existe un error al nombrar igual dos estilos, simplemente el último sobreescribe al primero dada la característica de cascada de CSS). Este problema se encuentra acentuado al intentar reutilizar elementos o añadir nuevos desarrolladores a un equipo. En el caso de reutilizar componentes se debe a que además de aislar la funcionalidad y estructura del componente en cuestión a ser reutilizado, también se debe buscar dentro del archivo CSS (que contiene los estilos de toda la aplicación) las clases necesarias para su correcta visualización. Mientras que en el caso de añadir un nuevo desarrollador el problema subyace en que debe comprender la notación CSS utilizada por el equipo, y además leer todo el código cada vez que desee crear un nuevo componente para evitar duplicar nombres de clases y causar conflictos con componentes ya existentes. Pese a que en los últimos años se intentó guiar el desarrollo hacia componentes desacoplados con estilos separados por cada uno de ellos, pero este enfoque de desarrollo agrega un problema adicional que es la necesidad de configurar sistemas de construcción de paquetes más complejos.

Referencias

Documento similar

&#34;No porque las dos, que vinieron de Valencia, no merecieran ese favor, pues eran entrambas de tan grande espíritu […] La razón porque no vió Coronas para ellas, sería

n que se contiene La Ordenanza que generalmente deberá observarse para el modo de.. cazar y pescar en estos rey nos, con señalamiento de los tiempos de veda, de una y

The part I assessment is coordinated involving all MSCs and led by the RMS who prepares a draft assessment report, sends the request for information (RFI) with considerations,

“La unificación de la clasificación de empresas otorgada por las CC.AA.”, “La unificación de criterios en la acreditación de los servicios de prevención de riesgos

En el capítulo de desventajas o posibles inconvenientes que ofrece la forma del Organismo autónomo figura la rigidez de su régimen jurídico, absorbentemente de Derecho público por

La solución que se ha planteado, es que el paso o bien se hiciese exclusivamente por el adarve de la muralla, o que una escalera diese acceso por la RM evitando la estancia (De

Volviendo a la jurisprudencia del Tribunal de Justicia, conviene recor- dar que, con el tiempo, este órgano se vio en la necesidad de determinar si los actos de los Estados

Cuando trabaje en una tabla, haga clic donde desee agregar una fila o columna y, a continuación, haga clic en el signo más.La lectura es más fácil, también, en la nueva vista