¿JavaScript Atómico Compilado?

This ad is not shown to multipass and full ticket holders
JSNation US
JSNation US 2025
November 17 - 20, 2025
New York, US & Online
See JS stars in the US biggest planetarium
Learn More
In partnership with Focus Reactive
Upcoming event
JSNation US 2025
JSNation US 2025
November 17 - 20, 2025. New York, US & Online
Learn more
Bookmark
GithubProject website
Rate this content

¿Podemos aplicar las lecciones de CSS a JavaScript?

Mientras trabajamos en StyleX usamos la compilación y la técnica Atomic CSS para crear un sistema más eficiente. Tener pequeñas reglas CSS atómicas maximiza la reutilización y reduce drásticamente el tamaño del CSS a escala. Un compilador potente hace que el proceso sea automático y libera de tener que pensar en DSLs personalizados. 

¿Podemos hacer lo mismo para JavaScript? ¿Cuáles serían las compensaciones? ¿Puede resultar en beneficios únicos no posibles con la mayoría de los otros enfoques?

This talk has been presented at React Summit 2025, check out the latest edition of this React Conference.

Naman Goel
Naman Goel
22 min
13 Jun, 2025

Comments

Sign in or register to post your comment.
Video Summary and Transcription
En 2008, la película Vantage Point inspiró la exploración de diversas perspectivas en el desarrollo de software. La evolución del CSS tradicional a estilos atómicos en StyleX y la ventaja de escalabilidad de JavaScript atómico son áreas de interés significativas. Repensar el renderizado del lado del servidor con React, Web Components y el marco Hano introduce nuevas posibilidades para componentes interactivos. Los elementos personalizados, Shadow DOM y el marco Solenoid abordan desafíos en el alcance de CSS y SSR para HTML más ligero. Las funciones de señal en Solenoid ofrecen un enfoque único para la gestión de datos y el desarrollo de componentes, mejorando la eficiencia de la aplicación. La configuración interactiva en tiempo real del servidor, el desarrollo innovador del lado del servidor y el uso de HTML como fuente de verdad contribuyen a la velocidad y eficiencia del proyecto. La depuración, la definición de componentes, la transmisión de HTML y el uso de componentes destacan la naturaleza declarativa y las capacidades de transmisión del HTML generado por el servidor.
Available in English: Compiled Atomic JavaScript?

1. Explorando StyleX y Atomic JavaScript

Short description:

En 2008, la película Vantage Point mostró diversas perspectivas. StyleX, una solución de CSS y JS en tiempo de compilación, ofrece estilos atómicos optimizados. La ventaja de escalabilidad de Atomic CSS sobre el CSS tradicional es significativa. ¿Puede Atomic JavaScript replicar este éxito en el ámbito de JavaScript?

En 2008, hubo una película llamada Vantage Point. Era una historia contada desde muchas perspectivas diferentes, y ves cómo las diferentes perspectivas pueden ser muy diferentes entre sí y contarte diferentes historias. Pero luego, cuando las juntas todas, puede surgir algo nuevo. De todos modos, soy Naman, trabajé en Meta durante ocho años. Y durante los últimos cuatro a cinco años, estuve trabajando en StyleX. Entonces, ¿qué es StyleX? Es una solución de estilo CSS y JS, pero es en tiempo de compilación, por lo que no hay inyección de estilo en tiempo de ejecución. Produce una hoja de estilos atómica altamente optimizada, similar a Tailwind. Yo diría que es una de las mejores soluciones de estilo que existen, mucho mejor que Tailwind. Hay algunas otras que la gente no conoce, pero eso no viene al caso. Independientemente, el punto importante es que el concepto de Atomic CSS está ganando. Pero no siempre fue así. Hubo un largo tiempo en el desarrollo web donde los paquetes cargados de manera diferida eran ubicuos. Teníamos paquetes específicos de ruta de CSS, los cargábamos de manera diferida a medida que navegábamos por las páginas, usábamos extensiones de sintaxis como Sassless, y usábamos arquitecturas como BEM y OOCSS, que en realidad era algo que teníamos que aprender, y no había herramientas para ello. Pero luego llegó Atomic CSS y cambió completamente la ecuación. Y la razón por la que tuvo tanto éxito es que simplemente escala mejor. En lugar de que tu CSS crezca con el número de componentes, donde simplemente obtienes CSS más y más grande, con Atomic CSS, después de un tiempo, tu CSS simplemente deja de crecer. Y como resultado, puedes tener un pequeño paquete de CSS cargado todo al frente. No necesitas cargar más CSS de manera diferida. Tu HTML se vuelve un poco más grande, claro. Tienes más nombres de clase. Pero en general, un HTML más grande sigue siendo mucho más barato que un archivo CSS más grande. Y a escala, te das cuenta de cómo un archivo CSS grande puede convertirse en un cuello de botella de rendimiento, que de otro modo no notarías. Así que comencé a pensar, ¿podemos hacer también Atomic JavaScript y cambiar la ecuación en el mundo de JavaScript?

2. Rethinking Server-Side React and Web Components

Short description:

He usado React durante 12 años, explorando el renderizado del lado del servidor hasta los componentes recientes orientados al servidor. ¿Pueden los componentes del servidor ser interactivos? La simplicidad de HTMX atrae, pero carece de estructura declarativa y consistencia de componentes. Profundizando en JSX, el marco Hano y el Shadow DOM de Web Components para el aislamiento de estilos.

He estado usando React durante los últimos 12 años, y comencé a usarlo para el renderizado del lado del servidor. Pasé por React Create class, componentes de clase ES6, componentes de función con componentes de orden superior, Redux, y luego Hooks. Pero luego, este gran cambio ocurrió recientemente, llamado RSCs. Y RSCs de alguna manera voltearon el modelo de React, donde ahora todo es orientado al servidor. Los datos son orientados al servidor. Comenzamos a pensar, ¿por qué enviar componentes al cliente si la salida siempre va a ser estática? Podemos tener un paquete de cliente más pequeño si gran parte de nuestra UI puede ser representada con datos o marcado en esta situación. Todavía podemos tener componentes de cliente para la interactividad.

Así que comencé a pensar, ¿pueden los componentes del servidor ser interactivos por sí mismos? Hola, soy Naman, y no soy fan de HTMX. Pero hay algunas cosas que todavía me parecen interesantes al respecto. Así que este es un demo muy simple de HTMX, y lo que me gusta de él es que la lógica de tu aplicación está justo ahí en el HTML. No hay JavaScript extra para cargar, no hay paquetes adicionales. Todo se reduce a algo muy simple, muy eficiente, en términos de los datos que tienen que cargarse en el navegador. Pero también, HTMX tiene lógica imperativa por todas partes. Estás actualizando cosas por IDs y inner HTML y outer HTML. No hay un sistema declarativo para hacer un seguimiento de todo y no hay componentes, no hay flujo de datos consistente.

Eventualmente, comienza a sentirse como jQuery con pasos adicionales. Pero luego también, por otro lado, JSX puede usarse sin React. Y hay un marco de servidor llamado Hano. Es un competidor de Express, que tiene soporte de primera clase para JSX, pero solo para renderizar HTML regular. Y así comencé a pensar, ¿podría hacer un modelo de componente declarativo que genere algo como HTMX? Hola, soy Naman, y no soy un gran fan de Web Components. Pero he estado investigando las APIs, buscando algo de valor en todo eso que hemos construido y puesto en los navegadores. Así que comencé a mirar qué son los Web Components, qué compone los Web Components. Así que la primera cosa de la que todos hablan, porque es la parte más controvertida, es Shadow DOM. Shadow DOM te da aislamiento de estilos. Ese es su gran valor. Cualquier CSS fuera del Shadow DOM no se aplica al mockup dentro del Shadow DOM, y cualquier CSS dentro del Shadow DOM no afecta nada fuera de él. Pero ahora tenemos Atomic CSS. No tenemos conflictos. No necesitamos este alcance de CSS en la mayoría de los casos.

3. Exploring Custom Elements and Solenoid Framework

Short description:

Desafíos de alcance de CSS y SSR. Shadow DOM para casos específicos. Etiquetas de plantilla y elementos personalizados con eventos de ciclo de vida. Uso de elementos personalizados para HTML más ligero e introducción de Solenoid, un framework de JavaScript atómico orientado al servidor.

No necesitamos este alcance de CSS en la mayoría de los casos. Y realmente hace que SSR sea difícil, o a veces imposible, si tienes que soportar navegadores más antiguos. Así que mi conclusión fue que solo es realmente útil para algunos casos especiales. Como si estuvieras tratando de construir tu propio demo tipo CodePen, podrías necesitar algo como Shadow DOM para encapsular estilos arbitrarios. Pero para mis casos de uso, vamos a quemarlo en el fuego. No lo quiero.

A continuación, están las etiquetas de plantilla. Son solo cadenas. Son solo cadenas que viven en HTML. No las odio, pero tampoco son tan emocionantes. Finalmente, están los elementos personalizados. Los elementos personalizados son simplemente cualquier elemento donde pones un guion en el nombre. Pero tienen algo de valor, que es que te dan eventos de ciclo de vida para montaje, desmontaje y actualizaciones. Sin elementos personalizados, en realidad no hay eventos en HTML para hacer eso.

Tienes que usar observadores de mutación y rastrear cuándo se está cargando HTML, lo que tampoco te dice cuándo algo se descarga. Así que hace esa parte un poco más fácil. Así que podría haber algo de valor aquí. Usando eso, creo que debería ser posible poner algo de lógica, algo de programación en HTML mismo, convertir este lenguaje de marcado en un lenguaje de programación. Así que comencé a pensar, ¿podrían usarse los elementos personalizados para crear un HTML más ligero o algo así? Si estás mirando todas las perspectivas, podrías estar juntándolo todo, descifrándolo o podrías estar realmente, realmente confundido. ¿De qué demonios estoy hablando? Solo espera. Lo explicaré. Tendrá sentido.

Sí, construí un nuevo framework. Presentando Solenoid. Es como SolidJS, pero con pasos adicionales. Es un framework de JavaScript atómico orientado al servidor. Es JSX en el servidor. Los componentes están en el servidor. Las señales se definen en el servidor, pero luego se implementan en HTML. Y luego todo se ejecuta en el navegador.

4. Understanding Signal Functions in Solenoid

Short description:

Visión general de alto nivel sobre cómo escribir código al estilo React y SolidJS. Elemento personalizado para la definición global de señales. Funciones de señal en lugar de datos, usando elementos personalizados para actualizaciones de datos, y componentes de Solenoid que se asemejan a SolidJS con señales alienígenas.

Entonces, ¿cómo funciona? Para darte una visión general de alto nivel, escribes código como este, que es muy al estilo React, SolidJS, y el framework genera algo que se ve así. Este es un elemento personalizado que define la señal globalmente en el HTML para que otro HTML pueda usarlo. Pero no tienes que escribir este código desagradable de componente web de elemento personalizado. Puedes escribir código como este, que es, nuevamente, muy al estilo SolidJS o React, excepto que en lugar de estado, tienes señal, por lo que son funciones. Todo son funciones en lugar de datos.

Y luego el framework genera algo que se ve así, que nuevamente usa un elemento personalizado que le dice qué señal buscar, enlazar y suscribirse para que los datos puedan ser actualizados. ¿Así que quieres ver una demostración? Muy bien. Tengo que cambiar. Así que antes de continuar, este es un archivo HTML. Es una salida. El framework todavía está muy en construcción. Así que más o menos funciona. Es un componente contador. Sabemos cómo se ve eso. Pero déjame mostrarte lo que se necesitó para construirlo.

Así que el componente contador se ve muy similar a cualquier Solid... Más grande. Más grande. ¿Está mejor? Muy bien. Piérdete. Bien. Así que un componente en Solenoid se parece a SolidJS. La API de señal es ligeramente diferente, porque está usando señales alienígenas, donde la señal es una función que es tanto un lector como un escritor. Así que si lo lees sin... Si lo llamas sin argumentos, es una lectura. Si lo llamas con argumentos, es una escritura. Aparte de eso, es igual que SolidJS. No hay sintaxis especial. Todas las funciones flecha se compilan de cierta manera. Todas las funciones no flecha se tratan como componentes.

5. Efficient Compilation Process in Solenoid

Short description:

Generación de código con un pequeño runtime, funciones JavaScript atómicas, definición de señales y compilación de componentes para un desarrollo de aplicaciones eficiente sin procesamiento en el servidor.

Entonces escribes algo como esto. Y luego genera un código que se ve así. Así que en la sección de head, hay un pequeño runtime que se carga en todas las aplicaciones. El runtime actualmente es de nueve kilobytes. Actualmente le faltan un par de características, por lo que aún no hay context o suspense. Así que como máximo, debería ser de 20 kilobytes. Y aparte de eso, no debería haber JavaScript adicional del framework. Aparte de eso, el único JavaScript que termina en el navegador son funciones flecha específicas, que se compilan para extraer el closure. Te mostraré cómo funciona eso en un segundo.

Y de nuevo, lo he simplificado un poco, solo para ver. En una aplicación de producción real, esto sería una declaración de importación, y las funciones se deduplicarían. Así que la parte importante aquí es que mencioné JavaScript atómico hace un momento. Estas funciones serán hashed. Así que si usas la misma lógica en múltiples lugares, incluso con datos diferentes, se hash al mismo ID y se reutilizará en múltiples partes de tu aplicación, al igual que CSS atómico. Y luego definimos una señal, que es un count. Definimos algunos botones que actualizan ese count. Definimos un texto de señal que usa ese count. Y luego ya hay ifs implementados. Los bucles están en progreso en este momento. Y eso es lo que te da este código funcional. Y es literalmente ese archivo HTML. No hay magia extra aquí. Ni siquiera está pasando por un servidor en este momento.

Para mostrarte el paso de compilación de esto, vuelvo al contador. Así que ese contador se compila en algo que se ve así. Así que esta parte es mayormente JSX, por lo que no es súper interesante. Lo que es más interesante son todas las funciones que escribes, cada función flecha que escribes en tu componente, podría estar usando algunos datos que son un parámetro o un argumento, pero podría estar usando otros datos que simplemente estaban alrededor en el closure. Así que el compilador detecta todo lo que se usó del closure, lo convierte en otro argumento llamado closure, y lo convierte en una función independiente que puede ser serializada y enviada al servidor, que es cómo funciona esto. Listo para mostrarte, bien, eso está corriendo allí. Así que cuando ejecutas ese componente a través de la función render en el servidor, genera un stream que se ve algo así.

6. Real-Time Interactive Server Setup

Short description:

Generación de funciones, señales y streaming interactivo sin hidratación. Configuración especial del servidor para interactividad en tiempo real antes de Contentful Paint. Agradecimiento a un compañero de trabajo por la asistencia en el framework y discusión de compensaciones en el proyecto.

Entonces está generando etiquetas de script que definen funciones, está generando let signal que define la señal, y define todo el HTML que te mostré en el archivo HTML de todos modos.

Una demostración final, que está aquí, y volveré a por qué esto funciona, pero una de las grandes propuestas de valor de por qué comencé a construir esto es que no hay hidratación. Es interactivo mientras se transmite. Así que este es un servidor especial que he creado que transmite el mismo archivo HTML línea por línea, y hay un retraso de un segundo entre cada línea. Así que solo quiero mostrarte cómo funciona eso. Así que no ves nada por un tiempo, luego ves el count. Ya es interactivo mientras el HTML todavía se está transmitiendo, y cuando el double count llega, ya se está actualizando también, y luego cuando llega la cosa final, ya es interactivo también. Así que no hay retraso para la interactividad. No hay tiempo para interactuar. La interactividad ocurre antes de Contentful Paint, esencialmente.

Así que volviendo a la pantalla extendida, volviendo a keynote. Así que quiero dar un agradecimiento especial a Vikram Rangarajan. Él fue mi compañero de trabajo en Meta hace unos años. Ayudó con gran parte del framework. No habría podido construir todo esto a tiempo para la conferencia, así que solo quería hacer eso. Justo después de eso, surge la pregunta de, ¿es toda esta cosa una muy mala idea? Así que hay algunas compensaciones y desconocidos bastante importantes. Así que, en primer lugar, todo esto apenas funciona en este momento.

7. Innovative Server-Side Development

Short description:

Desarrollo de nuevos conceptos, características del lado del servidor, desafíos con selectores CSS y la singularidad de usar Atomic CSS. Potenciales beneficios de velocidad y consideraciones de elementos personalizados en el proyecto.

Es muy, muy nuevo. Esto fue solo una idea loca que tuve hace aproximadamente un año, y he estado pensando en ello por un tiempo, y decidí construirlo para la conferencia. Está lejos de estar completo en cuanto a características, aunque tengo una idea de cómo cada característica que queremos en una aplicación real funcionaría. Suspense funcionaría. La obtención de datos en componentes ya está implementada, pero suspense no lo está, así que no pude demostrar eso.

Así que solo los componentes asíncronos son una característica de primera clase porque todo es del lado del servidor. Rompe muchos selectores CSS. Como notarás en el HTML, hay un montón de etiquetas adicionales, elementos adicionales. Así que si haces cualquier selector de hijo directo o selector de hermano directo, esos no son confiables. Así que asumo que usarás Atomic CSS. Hay una manera de solucionarlo. También podría escribir un plugin de PostCSS, que haría que todos esos funcionen.

Pero en realidad creo que es mejor usar Atomic CSS y no depender de esos selectores. Genera un archivo HTML más grande. Asumo que eso es más rápido porque ha sido más rápido en otros dominios en los que he trabajado, pero esto es nuevo, así que no sé si realmente es más rápido. Tendremos que ver. Los elementos personalizados pueden no ser el mejor detalle de implementación. Y de hecho hay algunas otras soluciones similares, a las que llegaré en un segundo.

QnA

HTML Source of Truth

Short description:

Eliminación del problema de datos duplicados en los frameworks modernos al integrar todo el contenido en HTML. Discusión sobre la motivación detrás de la creación de un nuevo framework y sus cualidades únicas.

Pero también, podría ser una buena solución porque no hay problema de datos duplicados. Así que cada framework moderno hoy en día, cuando renderizas en el servidor, genera el HTML. Luego envía toda la carga de datos que usaste para la renderización del servidor y luego envía todos los componentes que se usaron para convertir esos datos en este marcado. Y luego se hidrata en el cliente, y luego simplemente repite todo dos veces. Así que estás enviando todo el HTML dos veces, una vez como el HTML, una vez como el componente. Y estás enviando todos los datos dos veces, una vez como el HTML y una vez como datos. Aquí todo está solo en el HTML y no hay duplicación alguna. No hay hidratación, no hay hidratación, así que todo es interactivo. Lo que significa que no hay errores de hidratación. El HTML es la fuente de verdad. Hola, soy Naman, accidentalmente creé un clon rápido de JS. Gracias.

Primero que todo, quiero hacer una pregunta para mí, que es clásica, como, oh tengo un problema para resolver, construyamos un framework. Y esto, de alguna manera, llevará a algunas de las otras preguntas, pero primero que todo, en qué momento dijiste, está bien, es tiempo de framework. ¿En qué momento el tipo de problema que estabas tratando de resolver llegó a un punto en el que dijiste, moverse hacia, construir algo nuevo es la estrategia? Así que diría que no fue de esa manera. No estaba tratando de resolver un problema. Esto era una idea. Y fue solo, como, honestamente, no sé si este framework es una buena idea o una mala idea mientras mi conferencia terminaba. Sé que tiene algunas cualidades interesantes. Es diferente de cómo todo funciona hoy en día. Eventualmente puede ser bueno o malo, pero solo lo construí porque tenía curiosidad si era posible. Y ese fue como mi viaje de, tenía todos estos pensamientos. Estaba viendo la transmisión de Ryan Carnazzo en YouTube, quien es el creador de Solid.js. Así que he estado viendo cosas en esta industria, he estado obteniendo todas estas ideas. He estado viendo a la gente quejarse de cosas. Y fue como, esta idea se formó durante el último año. Fue como, déjame ver si es posible. Y resulta que es posible. Así que veremos. Eso tiene sentido.

Debugging and Component Definition

Short description:

Discusión sobre la depuración en el framework, destacando los beneficios de la naturaleza declarativa para una depuración más sencilla. Aclaración sobre la importancia de la forma de la función y la restricción de usar funciones flecha para definir componentes.

Eso tiene sentido. Muy bien, tenemos algunas preguntas llegando. Gracias, y sigan enviándolas. La primera es ¿cómo realizas la depuración en tu framework? Hay muchas herramientas de desarrollo diferentes que la gente puede usar integradas en los frameworks que tienen. Entonces, ¿cómo abordarías la depuración, y tal vez es algo que vas a resolver en el futuro? Sí, así que primero, honestamente, no lo he pensado. Apenas logré que la demo funcionara. Hice que la última demo de streaming funcionara hace dos horas. Así que no está muy terminado ni nada. Pero solo pensándolo, dado que todo es tan declarativo, ya que todo el flujo de datos está representado en HTML, supongo que la depuración sería mucho más fácil, especialmente para el rendimiento. Porque no sé si la gente está familiarizada con todas las herramientas que David Cappiano de ¿cómo lo llamas? Next state. Next state. Sí. Es conocido por construir visualizaciones realmente geniales. Para construir visualizaciones geniales, necesitas datos estáticos que puedas consumir. Usualmente con código, eso no es fácil porque tienes código y en el mejor de los casos obtienes ASTs. Pero aquí, tienes todo el flujo de datos, como todo el árbol de dependencias de datos representado en tu HTML. Así que hay un montón de herramientas posibles donde podrías simplemente mirar el gráfico generador de HTML, puedes ver qué tan bien está funcionando. Y puedes ver qué elementos específicos son lentos y cuáles son rápidos.

Oh, no, me encanta eso. Esa es una respuesta muy, muy detallada. Y la siguiente es una pregunta de aclaración de alguien, que es, ¿entendieron correctamente que la forma de la función es significativa? Entonces, ¿no se pueden usar funciones flecha para definir un componente? Sí, esa es actualmente la decisión sobre cómo funciona el compilador. Así que Quick.js, que es muy similar en muchos aspectos. Hicieron algunas como la implementación es completamente diferente. Fue después de que había construido como el 80 por ciento de esto que se me señaló que es en realidad algo similar a Quick.js. Usan muchas funciones envolventes y signos de dólar para indicar qué se compila y qué no se compila. Y decidí que necesitaba todo dentro del componente compilado de todos modos. Así que estoy diciendo que los componentes deben ser declaraciones de función y todo dentro del componente debe ser funciones flecha y todo funcionará bien.

Eso tiene sentido. Tenemos otra. Esta es de Mikhail Vandaros Heinemann.

HTML Streaming and Component Usage

Short description:

Explicación sobre la transmisión de HTML y JavaScript al navegador, aclarando la combinación de ambos en el HTML generado por el servidor. Detalles sobre el uso de componentes en otros archivos sin cargar todo el JavaScript atómico compilado cada vez.

Si la lógica del front end cambia el DOM anidado, el DOM anidado en lugar de texto y la notación es JSX, ¿estás transmitiendo HTML o JavaScript al navegador? Es una combinación de ambos. Así que de nuevo, en mi demo de HTML, sí, fue una demo muy mínima. Espero que tuviera algo de sentido, pero es principalmente solo transmisión de HTML. Todo se convierte a HTML en el servidor, pero el HTML contiene pequeños fragmentos de JavaScript, que son las cosas que no pueden ser representadas en HTML, que son nuevamente, manejadores de eventos y transformaciones de datos y eso es todo.

Eso tiene sentido. Muy bien, tenemos tiempo para una más. ¿Cómo puedes usar los componentes en otros archivos? ¿Se carga todo el JavaScript atómico compilado cada vez que los usamos? No, solo lo que realmente se renderiza se transmite al cliente. De hecho, no hay ningún empaquetador. No empaquetas tu JavaScript para enviarlo al cliente. Escribes código del servidor y el tiempo de ejecución del servidor genera HTML en tiempo de ejecución y eso es todo.

Eso es increíble. Estoy seguro de que hay muchas personas que quieren alguna aclaración, quieren responder algunas preguntas más. Pueden encontrarte en el lugar de preguntas y respuestas de los ponentes. Muchas gracias. Vamos a tener un breve descanso. Recuerden, si se quitan los auriculares, déjenlos en su silla y demos un aplauso.