Traducción de plantillas Dust a JSX



Hola habr Soy MiloŇ° de Badoo, y esta es mi primera publicaci√≥n de Habr, publicada originalmente en nuestro blog de tecnolog√≠a . Espero que les guste, y por favor compartan y comenten si tienen alguna pregunta

Entonces ... ¬Ņreaccionar, amirita?

Apareció a mediados de la década (plagada por las interminables guerras de framework JavaScript), abrazó el DOM , sorprendió a todos al mezclar HTML con JavaScript y transformó el panorama del desarrollo web más allá del reconocimiento.

Todos esos logros, sin siquiera ser un marco .

Me encanta o lo odio, React hace un trabajo realmente bien, y eso es la plantilla HTML. Junto con una gran comunidad y un ecosistema saludable, no es difícil ver por qué se convirtió en una de las bibliotecas de JavaScript más populares e influyentes, si no la más popular de todas.


Aqu√≠ en el equipo de Mobile Web, no seguimos ning√ļn marco JS estricto, o al menos ninguno popular, y usamos una combinaci√≥n de tecnolog√≠as heredadas y modernas. Aunque eso funciona bien para nosotros, la manipulaci√≥n de DOM suele ser dif√≠cil, y quer√≠amos aliviar esto reduciendo el n√ļmero de actualizaciones "manuales", aumentando la reutilizaci√≥n de nuestro c√≥digo y preocup√°ndonos menos por las p√©rdidas de memoria.

Después de un poco de investigación, React se consideró la mejor opción y decidimos ir con ella.

Me uní a Badoo en medio de este proceso. Habiendo iniciado y trabajado en proyectos de React anteriormente, estaba al tanto de sus pros y sus contras en la práctica, pero migrar una aplicación madura con cientos de millones de usuarios es un desafío completamente diferente.

Jsx


React mezcla HTML con JavaScript en un formato llamado JSX . Aunque parece un lenguaje de plantilla, JSX es en realidad solo una sintaxis o un az√ļcar sint√°ctico si, para las llamadas de React, tiene un aspecto muy similar al HTML.

Nuestros propios archivos HTML estaban bien organizados, y la mayor parte de nuestra representaci√≥n se realiz√≥ tan simplemente como template.render() . ¬ŅC√≥mo podr√≠amos retener este orden y simplicidad mientras nos movemos a Reaccionar? Para m√≠, aparte de las dificultades t√©cnicas, una idea era obvia: reemplazar nuestras llamadas existentes con c√≥digo JSX.

imagen


Después de una planificación inicial, lo probé y envolví una herramienta de línea de comandos que realiza dos cosas simples:

  1. Lee las plantillas referenciadas en el archivo UI (JavaScript)
  2. Reemplace las llamadas de template.render() con el contenido HTML

Por supuesto, esto solo nos mover√≠a a la mitad, porque a√ļn tendr√≠amos que modificar el c√≥digo HTML manualmente. Considerando el volumen y el n√ļmero de nuestras plantillas, sab√≠a que el mejor enfoque ser√≠a algo automatizado. La idea original sonaba bastante simple, y si se puede explicar, se puede implementar.

Despu√©s de mostrar la herramienta inicial a los compa√Īeros de equipo, la mejor respuesta que obtuve fue que hay un analizador disponible para el lenguaje de plantillas que usamos. Eso significa que podr√≠amos analizar y traducir c√≥digo mucho m√°s f√°cilmente que con expresiones regulares , por ejemplo. ¬°Fue entonces cuando realmente supe que esto funcionar√≠a!

imagen


He aquí que, después de varios días, nació una herramienta para convertir plantillas tipo Dust.js HTML a código JSX React. Utilizamos Dust, pero con una amplia disponibilidad de analizadores sintácticos, el proceso debería ser similar para traducir cualquier otro lenguaje de plantillas popular.

Para obtener más detalles técnicos, salte a la sección de código abierto a continuación. Utilizamos herramientas como Esprima para analizar el código JS y un generador de analizador PEG.js para analizar las plantillas de Dust. En los términos más simples, se trata de traducir este tipo de código de plantilla:

 <div class="encounters {?isExpanded}is-expanded{/isExpanded}"> {?showTooltip} <div class="tooltip"> <span>{#_t}{encounters_tooltip}{/_t}</span> <div class="icon"> {@Icon name="icon-encounters" size="stretch" /} </div> </div> {/showTooltip} <div class="images"> {#images} <img src="{src}"> <input type="radio" id="{id}" {?selected}checked{/selected} /> <label for="showme-{id}"> {name} </label> {/images} </div> <div class="footer"> {! encounters-footer template will be injected here !} </div> </div> 

a su código JSX equivalente:

 <div className="encounters {props.isExpanded ? 'is-expanded' : ''}"> {props.showTooltip ? <div className="tooltip"> <span>{i18n.get('encounters_tooltip')}</span> <div className="icon"> <Icon name="icon-encounters" size="stretch" /> </div> </div> : null} <div className="images"> {props.images.map(item => <img src={item.src}> <input type="radio" id={`showme-${item.id}`} defaultChecked={item.selected ? true : undefined} /> <label htmlFor={`showme-${item.id}`}> {item.name} </label> )} </div> <div className="footer"> {/* encounters-footer template will be injected here */} </div> </div> 

Vea la comparación de lado a lado aquí .

Después de esto, nuestro proceso fue bastante sencillo. Convertimos automáticamente nuestras plantillas de un formato a otro, y todo funcionó como se esperaba (gracias, pruebas automatizadas). Para empezar, conservamos nuestra antigua API template.render() para mantener los cambios aislados.

Por supuesto, con este enfoque todavía terminas con plantillas y no con componentes React "adecuados". El beneficio real es el hecho de que es mucho más fácil, si no trivial, cambiar a React desde plantillas que ya son JSX, en la mayoría de los casos simplemente envolviendo un código de plantilla en una llamada de función.

Podr√≠as pensar: ¬Ņpor qu√© no escribir nuevas plantillas desde cero? La respuesta corta es que no hab√≠a nada malo con nuestras plantillas antiguas, simplemente ten√≠amos muchas de ellas. En cuanto a reescribirlos y trabajar hacia una verdadera componente, esa es una historia diferente .



Algunos podr√≠an argumentar que el modelo de componentes es solo otra tendencia que podr√≠a pasar, entonces, ¬Ņpor qu√© comprometerse con √©l? Es dif√≠cil de predecir, pero una posible respuesta es que no tiene que hacerlo . Si itera r√°pidamente, puede probar diferentes opciones, sin dedicar demasiado tiempo a ninguna de ellas, hasta que encuentre el formato que funcione mejor para su equipo. Ese es uno de los conceptos centrales para nosotros en Badoo.

Con el surgimiento de ES7 / 8 / Next, Elm y Reason, sin mencionar TypeScript y soluciones similares, el c√≥digo que alguna vez fue *.js est√° volviendo cada vez m√°s indistinguible de JavaScript, y parece que esa tendencia continuar√°. En lugar de sentirse abrumado por eso, ¬Ņpor qu√© no usar eso para nuestra ventaja?

Código abierto


En el espíritu de hacer bien una cosa , hemos construido estas herramientas internas en varias partes:

  1. dust2jsx : paquete responsable de la traducción real de polvo a jsx
  2. ratt (React All The Things): herramienta de línea de comandos para leer / escribir archivos en el disco. Responsable de incluir plantillas referenciadas, y utiliza dust2jsx internamente para transformar el código

Incluso hemos abierto estas herramientas: aseg√ļrese de revisarlas, as√≠ como otros materiales de c√≥digo abierto en nuestra p√°gina de GitHub . Contribuya o simplemente d√©jenos un comentario si los encuentra √ļtiles.

Source: https://habr.com/ru/post/437224/


All Articles