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