Dioxus 0.5: apps web, de escritorio y móviles desarrolladas con Rust
(dioxuslabs.com)- El framework GUI de Rust Dioxus 0.5 simplifica de forma importante el flujo de desarrollo web, de escritorio, móvil y Fullstack, centrado en la reescritura de
dioxus-corey la eliminación deunsafe - Entre 0.4.3 y 0.5.0 se incorporaron más de 100,000 líneas de código y más de 1,400 commits, y el nuevo core cambió en la dirección de eliminar dependencias de lifetimes y de
Scope - La gestión de estado anterior basada en
use_stateyuse_reffue reemplazada por una API deSignalque puede serCopy, reduciendo la carga deClonerepetidos en event handlers y futures - Con un solo flujo de
dioxus::launchydx serve --platform, se pueden ejecutar apps web, de escritorio y Fullstack, y el CLI pasa automáticamente los build features adecuados para la plataforma objetivo - También cambiaron la recarga en caliente de assets, la reescritura de eventos, las mejoras de renderizado de escritorio y el streaming de funciones de servidor, ampliando el alcance de una sola base de código Rust
Dirección del lanzamiento de Dioxus 0.5
- Dioxus es una librería para crear GUI con Rust, usada para desplegar apps web, de escritorio y móviles
- La versión 0.5 fue diseñada con el objetivo de lograr la simplificación, solidez y mayor nivel de acabado que pedía la comunidad
- Los cambios principales son los siguientes
- Reescritura completa de
dioxus-corey eliminación de código unsafe - Introducción de una API basada en
Signalen lugar deuse_stateyuse_ref - Eliminación de todos los lifetimes y del estado
cx: Scope - Una sola función
launchpara iniciar apps en todas las plataformas - Recarga en caliente de assets compatible con Tailwind y Vanilla CSS
- Reescritura de eventos que permite acceder a tipos de evento nativos de
WebSys - Integración de Error Boundary, Server Future y Suspense
- Mejora de 5 veces en la reconciliación de escritorio
- Streaming de funciones de servidor y hot reload para Fullstack
- Reescritura completa de
- Se ofrece una guía de migración para usuarios que actualicen desde Dioxus 0.4
Eliminación de lifetimes y Scope
- Desde Dioxus 0.1 hasta 0.4, los valores internos de los componentes tenían el lifetime
'bump, lo que permitía usar hooks, props y scope en listeners de eventos sin necesidad de clonarlos - En event handlers eso funcionaba bien en general, pero los futures de Dioxus debían ser
'static, así que era necesario hacercloneantes de mover valores dentro de un future - Cuando aparecían errores de lifetime, los mensajes podían decir que
cxdebía vivir más que'staticen vez de señalar el hook en sí, lo que generaba confusión - Dioxus 0.5 elimina
Scopey el lifetime'bump, y convierteElementen una forma sin lifetime - Los componentes ahora pueden recibir props directamente, sin parámetro de scope
- Ejemplo:
fn MyComponent(name: String) -> Element
- Ejemplo:
- Las funciones de runtime pueden usarse directamente no solo dentro de componentes, sino también dentro de futures y event handlers
- Al volverse
'static,Elementtambién puede usarse dentro de hooks o proveerse a través de la API de context - Este cambio sienta una base que facilita implementar APIs como listas virtuales u offscreen rendering
Eliminación de unsafe en dioxus-core
- La eliminación de
'bumpy de scope creó una oportunidad para reducir el código unsafe dentro de Dioxus dioxus-core 0.5no contiene código unsafe- Algunas dependencias todavía conservan pequeñas cantidades de unsafe, y el equipo de Dioxus planea eliminarlas durante el ciclo de lanzamiento de 0.5
- El unsafe restante se clasifica como código simplemente removible o código necesario por FFI
Gestión de estado basada en Signal
- Dioxus 0.5 introduce Signal como tipo primitivo central de estado para componentes
- Signal tiene dos ventajas frente a
use_stateyuse_ref- Siempre puede ser
Copy - No requiere suscripción manual
- Siempre puede ser
-
Estado Copy
Signal<T>esCopyincluso si el valor internoTno lo es- Este comportamiento es posible gracias al crate generational-box, implementado sin unsafe
- Si hace falta, Signal puede convertirse en
Send+Syncpara moverlo entre hilos - La combinación de estado Copy, Signal
Send+Syncy componentes static permite mover el estado fácilmente a futures, event handlers, hilos y otros lugares donde se necesite - El patrón de uso de memoria es casi igual al de 0.4, pero sin requerir
Cloneexplícitos
-
Suscripción inteligente
- Signal determina de forma más precisa qué componentes deben volver a ejecutarse cuando cambia un valor
- Un componente solo se vuelve a ejecutar si leyó el valor de Signal
- Las lecturas hechas dentro de tareas async o event handlers no se consideran suscripciones para reejecutar componentes
- Si el padre modifica un Signal al hacer clic en un botón pero no lee el valor directamente, y solo el hijo lo lee, entonces solo el hijo se vuelve a renderizar
- Gracias a esta estructura, ya no hace falta Fermi, que era un crate separado para gestión de estado
- Fermi ofrecía una API similar a
use_stateusandostaticcomo clave - En Dioxus 0.5, se puede colocar
GlobalSignalen unstaticy usarlo como un Signal normal - Signal también funciona con la API de context, por lo que es posible compartir estado entre componentes sin un hook separado
use_shared_state - Si se lee un Signal dentro de hooks como
use_futureouse_memo, ese Signal se agrega automáticamente a las dependencias del hook
Hot reload de CSS y assets
- Dioxus 0.5 implementa hot reload de archivos CSS del directorio de assets como parte de una renovación del sistema de assets
- Si un archivo CSS aparece en RSX, el CLI
dxobserva ese archivo y transmite las actualizaciones de inmediato a la app en ejecución - Esto es compatible con Web, Desktop y Fullstack; el soporte móvil llegará en una futura actualización centrada en mobile
- Si se usa junto con el watcher de Tailwind, también se admite hot reload de Tailwind CSS
- En VSCode, también se puede obtener sugerencias de clases Tailwind mediante la custom regex extension
- Los cambios pueden transmitirse a varios dispositivos al mismo tiempo para hacer hot reload en todos los dispositivos objetivo
Reescritura del sistema de eventos
- Desde su lanzamiento, Dioxus había usado un sistema de synthetic events para crear una API de eventos multiplataforma
- Los synthetic events son útiles para el comportamiento uniforme entre plataformas y la serialización por red, pero también tenían limitaciones
- Dioxus 0.5 expone los tipos de evento subyacentes de cada plataforma y además ofrece traits para la API multiplataforma
- Este cambio tiene dos ventajas
- Permite obtener directamente la información necesaria desde el tipo de evento de la plataforma o pasarla a otras librerías
- Permite hacer bundle splitting del código de eventos que la app no use
- En el ejemplo de hello world, el tamaño comprimido con gzip se redujo alrededor de 25%
- Consejos para generar bundles más pequeños están incluidos en la guía de optimización de Dioxus
API de ejecución multiplataforma
- Dioxus 0.5 introduce una nueva API multiplataforma para ejecutar apps
- En lugar de importar paquetes renderer separados, basta con activar features en el crate
dioxusy llamar a la funciónlaunchdel prelude - Una misma app puede ejecutarse para las siguientes plataformas
- Desktop:
dx serve --platform desktop - SPA Web:
dx serve --platform web - Fullstack:
dx serve --platform fullstack
- Desktop:
- El CLI pasa automáticamente los build features adecuados según la plataforma objetivo
Beta del sistema de assets y Manganis
- En Dioxus y en las apps web, las rutas de assets tienden a quedarse obsoletas, los enlaces pueden diferir entre desktop y web, y suele ser necesario agregar manualmente los assets que se incluirán en el bundle
- Los assets también pueden convertirse en un cuello de botella de rendimiento
- En el ejemplo de la guía de Dioxus Mobile, la versión 0.4 tardaba 7 segundos en cargar y transfería 9 MB de recursos
- La guía móvil de 0.5 usa la misma imagen, pero carga en menos de 1 segundo y reduce los recursos necesarios a 1/3
- Dioxus 0.5 introduce el nuevo sistema de assets manganis
- Se integra con el CLI para revisar, empaquetar y optimizar los assets de la app
- La API todavía es inestable, por eso se distribuye como crate separado
- Si se envuelve un asset con la macro
mg!, el CLI lo detecta automáticamente - Más detalles están en la documentación de manganis
- Durante el avance del lanzamiento 0.5, planean agregar hot reload también a los assets de manganis
Mejora de 5 veces en el renderizado de escritorio
- Dioxus usa varias optimizaciones para generar rápidamente los diffs de renderizado
- Templates permite omitir el diff de las partes estáticas en la macro
rsx! - En Dioxus Web, los cambios al DOM se aplican rápidamente desde Rust mediante sledgehammer
- Dioxus 0.5 aplica el mismo enfoque también a los cambios enviados por red
- Los renderers Desktop y LiveView se comunican con un protocolo binario en lugar de JSON
- En tareas con alta carga de renderizado, el nuevo renderer reduce a 1/5 el tiempo necesario para aplicar cambios en el navegador y reduce la latencia a la mitad
- Un benchmark en el que el renderer de Dioxus 0.4 se detenía constantemente ahora se ejecuta con fluidez en Dioxus 0.5
Funciones de conveniencia al escribir componentes
- Dioxus 0.5 permite extender un element específico y expandir atributos dentro del element
- Ejemplo: en un componente
ImgPlusque extiende los atributos de un elementimg, se pueden recibir directamente atributos comunes deimgcomowidth,heightysrc
- Ejemplo: en un componente
- Al pasar valores a atributos y componentes, se puede usar la sintaxis abreviada de inicialización de structs
- Se puede escribir
classen lugar declass: class
- Se puede escribir
- Los atributos abreviados funcionan con cualquier elemento que implemente
IntoAttribute, y Signal también se beneficia de esto - Los atributos Signal todavía no omiten el diffing, pero planean añadir esa optimización durante el ciclo de lanzamiento 0.5
- Los atributos divididos en varias líneas pueden fusionarse
- Si se añaden valores condicionales al mismo atributo
class, se fusionan usando espacios como separador - Esto es importante para librerías como Tailwind, que requieren parsing en tiempo de compilación pero también procesamiento dinámico en runtime
- Esta sintaxis se integra con el compilador de Tailwind y elimina la sobrecarga de runtime de librerías como
tailwind-merge
- Si se añaden valores condicionales al mismo atributo
Streaming de funciones de servidor y Fullstack
- Dioxus 0.5 es compatible con la versión más reciente del crate de server functions, que soporta datos en streaming
- Las funciones de servidor pueden transmitir datos al cliente o del cliente al servidor
- Las funciones de servidor con streaming pueden crearse definiendo un tipo de salida y retornando
TextStreamdesde la función de servidor - Esto resulta adecuado para actualizar al cliente durante tareas de larga duración
- Hay un ejemplo que usa Kalosm y LLM locales para ofrecer en hardware común una funcionalidad similar al endpoint de OpenAI ChatGPT
- Repositorio de ejemplo: https://github.com/ealmloff/dioxus-streaming-llm
- El CLI ahora también soporta la plataforma
fullstacky ofrece hot reload y compilación en paralelo para cliente y servidordx servedx serve --platform fullstack
LiveView, asset handler y manejo de archivos
- En Dioxus 0.5, el router funciona por defecto en apps LiveView
- PR relacionada: https://github.com/DioxusLabs/dioxus/pull/1505
- Dioxus Desktop soporta custom asset handler
- PR relacionada: https://github.com/DioxusLabs/dioxus/pull/1719
- Un custom asset handler permite transmitir datos de forma eficiente al navegador desde código Rust sin pasar por JavaScript
- Esto es adecuado para comunicaciones de alto ancho de banda como video streaming
- PR relacionada: https://github.com/DioxusLabs/dioxus/pull/1727
- Es posible pasar datos de gstreamer o webrtc directamente al webview, reduciendo la necesidad de codificar y decodificar frames manualmente
- El file drop de escritorio también quedó integrado de forma nativa al sistema de eventos
Manejo de errores
- Dioxus permite manejar errores fácilmente en componentes superiores mediante Error Boundary y el trait
throw - El enfoque
throwcombina las ventajas del estado de error y del early return - En tipos
Resultque implementanDebug, se puede llamarthrowpara convertirlos en estado de error y usar?para hacer early return - El componente
ErrorBoundaryrenderiza otro componente cuando hay errores lanzados por sus hijos ErrorBoundarypuede anidarse, lo que permite capturar errores en distintos niveles de la app- Este patrón es útil para manejar un estado de error global sin hacer panic cuando ocurra un error no recuperable ni gestionar manualmente el estado de cada error
Experiencia de desarrollo y plantillas
- Dioxus introdujo hot reload en 0.3, lo agregó a Desktop en 0.4 y en 0.5 lo activa por defecto
- Si se ejecuta la app con
dx serve, el hot reload queda encendido por defecto en modo desarrollo - Incluso cuando en apps Desktop el hot reload no es posible y se requiere recompilar todo, se conserva y restaura el estado de la ventana abierta
- Se mantiene el tamaño y la posición de la ventana de la app
- Esto reduce las situaciones en que la app bloquea toda la pantalla con cada edición
- Las nuevas plantillas quedaron organizadas para crear apps Web, Desktop, Mobile, TUI y Fullstack con un solo comando
- La app por defecto de
dx newcambió a una forma más cercana a create-react-app- Incluye assets, CSS y configuración básica de despliegue
- Incluye enlaces a recursos útiles como dioxus-std, la extensión de VSCode, documentación y tutoriales
Dioxus Community y ecosistema
- Dioxus Community actualizó crates importantes del ecosistema para el lanzamiento 0.5
- Crates como icons, charts y una biblioteca estándar específica para Dioxus quedaron listos para usarse desde el momento del lanzamiento 0.5
- El proyecto
Dioxus Communityes una nueva organización de GitHub creada para mantener actualizados crates importantes incluso si el maintainer original se retira - Si alguien desarrolla una librería para Dioxus, el equipo puede ayudar con su mantenimiento y apunta a ofrecer soporte equivalente a un “Tier 2” de facto
Funciones planeadas a futuro
- Los planes después de 0.5 incluyen los siguientes puntos
- Estabilización del sistema de assets e integración más profunda
- Bundle splitting directo del
.wasmde salida junto con lazy component - Islands, resumable interactivity y serialización de Signal
- Fusión de server component y LiveView dentro de Fullstack
- Devtools y framework de testing mejorados
- Renovación completa de Mobile
- Renovación de Fullstack, incluyendo WebSocket, SSE y progressive form
Vista previa de Dioxus-Blitz basado en Servo
- En “Blitz 2.0” de Dioxus-Blitz se integra Servo para apuntar a renderizado nativo con WGPU usando el mismo motor CSS que al ejecutar Firefox
- Nico Burns, creador de la librería de layout Taffy, se unió de tiempo completo para impulsar este trabajo
- En la demo,
google.comse renderiza en la GPU a 900 FPS - La implementación actual todavía no está completa y el renderizado de
google.comaún se ve algo extraño, pero se está acercando rápidamente a un nivel utilizable - El repositorio puede verse en https://github.com/jkelleyrtp/stylo-dioxus
Cómo contribuir
- El proyecto Dioxus busca contribuciones en lo siguiente
- Traducción de documentación
- Probar “Good First Issues”
- Mejoras de documentación
- Contribuciones al CLI
- Responder preguntas en la comunidad de Discord
- El equipo de Dioxus agradece el apoyo de la comunidad durante el resto de 2024 y pide ayuda para transformar el desarrollo de apps
1 comentarios
Opiniones en Hacker News
Cuando empecé a trabajar era la versión 0.2, y con los cambios de esta 0.5 parece que casi toda la complejidad que sufrí entonces desapareció. Todavía no lo he probado directamente, pero la eliminación de lifetimes y la menor carga de tener que clonar constantemente deberían hacerlo mucho más cómodo.
Hay bastantes frameworks de Rust que intentan ofrecer una UI reactiva nativa desplegable en escritorio, web/wasm, móvil, etc. https://github.com/flosse/rust-web-framework-comparison, así que me preocupa elegir mal y tener que mantener un framework abandonado o hacer una migración dolorosa.
Con los frameworks de servidor HTTP en Rust pasó algo parecido: había muchos, y ahora parece que Axum, Actix y Rocket van a la cabeza; además, la comunidad parece estar moviéndose hacia Axum, así que a veces me pregunto si elegir Actix fue un error. Me interesa saber si hay señales de que Dioxus vaya a ganar, o si además de una comunidad grande, el apoyo de YC y el momentum, hay indicadores de que sea una buena elección hoy.
También quiero saber si Leptos y Yew son competidores principales, y por qué serían mejores o peores que Dioxus. Mi empresa ha invertido mucho en Rust, Actix y Bevy, y más adelante queremos combinar frameworks como Bevy y Dioxus para crear clientes nativos de escritorio y móvil.
Y también me da curiosidad si el nombre Dioxus viene de Deoxys, el Pokémon. El logo da esa impresión, pero en el código no hay referencias a Pokémon.
Hace unos 9 meses hice con Dioxus un frontend GUI para sshfs, y hasta que choqué con el muro de alguna función que los desarrolladores todavía no habían terminado, me pareció un framework GUI realmente excelente.
Compartir estado entre distintos contextos también duele a veces, pero me ha pasado con todos los frameworks GUI que he usado, sin importar el lenguaje o la tecnología base. Dioxus 0.5 parece un gran avance en ese punto. Mi blog renderiza una buena parte del HTML con Dioxus, y como no lo estoy llevando al límite, funciona muy bien.
Dicho eso, la solución de eliminar lifetimes me parece un poco extraña. generational-box me suena a una especie de recolector de basura para pobres, y me pregunto qué impacto tuvo en el rendimiento.
Además, el enlace
[generational-box]([https://crates.io/crates/generational-box](<https://crates.io/crates/generational-box>))está roto.use_hookposee el valor durante la vida del componente, así que cuando el componente desaparece, ese valor también se descarta. Todos los signals siguen usandouse_hook, por lo que su vida útil también es la misma. Normalmente no se recomienda llamar aGenerationalBox::new()fuera deuse_hook, así que no hay impacto en el rendimiento.Si abusas de
GenerationalBox::new()dentro de un loop, esa basura quedará hasta que se descarte el componente, pero en la mayoría de los casos estarás haciendo push/pop en un Map o Vec, y ahí se aplica la semántica de memoria normal.Entiendo que es una especie de asignación en arena, pero no entiendo cómo soporta “copiar sin copiar”, ni por qué es seguro que internamente cree una arena de
RefCellcon generaciones y queGenerationalBoxseaCopy.Entiendo que se pueden crear punteros a datos estáticos, pero me pregunto qué pasa con valores que no tienen vida útil estática.
Las referencias a los datos se mantienen durante toda la vida del programa. generational box permite meter datos que viven menos que el programa, pero esos datos no deben contener referencias. Cuando descartas los datos insertados, esa box se reutiliza para otra asignación.
Es un enfoque muy parecido a una arena generacional, salvo que usa boxes en vez de una arena centralizada; esa elección se hizo para evitar problemas de locks. Si intentas acceder a los datos con una referencia
Copydespués de que se descartaron, falla con un buen mensaje de error.Copytiene un significado específico.Si un tipo implementa el trait
Copy, significa que puede copiarse conmemcpy; no es una copia profunda, sino más bien una copia superficial.Así que no lo entiendo como “copiar sin copiar”, sino como permitir tratar tipos que no son
Copycomo si fueran tiposCopy. El README dice que se necesita contenido estático, así que para valores sin vida útil estática la respuesta es: “no se puede hacer eso”.Me gusta que Dioxus tome muchos de los elementos que hicieron exitoso a React, pero que además innove y despliegue rápido sobre esa base. Tengo ganas de probar los signals de este release.
Reconozco las cosas buenas que React hizo por JS y la web, y también su peso como nombre, pero si en 2024 puedes diseñar un lenguaje o DSL desde cero, no creo que el código de una “UI reactiva” tenga que verse necesariamente como React.
No digo que SwiftUI sea perfecto, pero el código escrito con SwiftUI se siente mucho más limpio, organizado y compartimentado que código similar escrito con React.
La verdadera ventaja de usar JSX para GUI multiplataforma es más o menos poder reutilizar bibliotecas existentes para la web, pero RSX parece tener poco “valor portable” aparte de permitir que los desarrolladores trasladen su conocimiento conceptual de JSX a RSX. Mejor sería un compromiso en el que se aprenda un paradigma nuevo que sea objetivamente superior al paradigma React/JSX.
En resumen, sería bueno que existiera un proyecto que fuera “SwiftUI, pero multiplataforma”, aunque todavía no existe. Conozco @Tokamak/TokamakUI, pero aún está muy incompleto y parece que la actividad bajó bastante.
Por ahora solo soporta apps de escritorio nativas para Linux/mac/windows, pero tiene planes de soporte para WASM, web y móvil.
Será el primer sitio web descentralizado que vean las personas que configuren Freenet. Se parece un poco a Kweb, el framework web en Kotlin en el que he trabajado de forma intermitente durante varios años, especialmente en el manejo de estado y en el enfoque DSL que mapea del código a HTML. Hasta ahora me gusta.
https://freenet.org/
https://kweb.io/
De hecho soy fan de Kotlin, y me gustan su DSL y su modelo de concurrencia.
Tauri mete el frontend en una webview, y para comunicarse con funciones nativas en Rust hay que pasar por un límite de IPC, como en Electron.
En Dioxus, como el código Rust está del lado nativo, no se necesita IPC para operaciones como leer el sistema de archivos o usar websockets. Tauri obliga a compilar el frontend a WASM, y muchas crates interesantes de Rust no compilan a wasm.
Es difícil expresar con palabras cuánto se simplifica el desarrollo cuando no hay un límite de IPC. Como las herramientas de Dioxus apuntan solo a Rust, puedes pasar de cero a una
.appempaquetada en menos de 1 minuto. Un build nuevo tarda unos 12 segundos, y un bundle nuevo unos 20 segundos.Aun así, me gusta mucho la flexibilidad que ofrece Tauri, es decir, que puedes usar como frontend cualquier UI compatible con la web, y también puedes usar Dioxus dentro de una app Tauri.
Me pareció bien que Dioxus lo abordara directamente en el README, pero también me interesan experiencias reales de gente que haya usado ambos.
Hice una app de escritorio de juguete con Tauri, y comprobé si el IPC era lo bastante rápido como para que el frontend web se actualizara y trabajara con cada pulsación de tecla sin latencia; la respuesta fue “sí”. Si era posible mandar un archivo grande desde el frontend a la capa de Rust en cada pulsación y recibirlo de vuelta en el frontend, al menos con mi implementación ingenua, la respuesta fue “no”.
Tanto Tauri como Dioxus tienen muchos casos donde encajan bien, y en algunos casos parece que Dioxus sería mejor. Me gustaría escuchar comparaciones tipo “en nuestro proyecto elegimos Dioxus o Tauri por X e Y”. Dioxus se ve realmente genial, y tengo ganas de probarlo.
stylo es la parte de Servo que se comparte con Firefox. A largo plazo nos gustaría mover a la gente al renderer WGPU, pero todavía está bastante verde, y muchas empresas que usan Dioxus saben de forma realista que una webview es una solución suficientemente buena para alrededor del 90% de una app.
Entiendo que a veces la gente usa
unsafedemasiado a la ligera, pero la biblioteca estándar también está llena deunsafe, y trazar la línea ahí a veces parece como dibujar una raya en la arena.Se usa en tres lugares: algunos ajustes de FFI en iOS, una implementación para permitir sintaxis de llamada a función en signal, y la implementación de Send/Sync para IDs que usan punteros como hash.
Viendo ahora esto último, tal vez se podría eliminar reemplazándolo por
usize.unsafe.Aun así, que el autor de una crate se proponga eliminar
unsafede su propia crate no necesariamente es una mala decisión.Los autores de crates que intentan eliminar todo
unsafea menudo buscan reducir la carga de confianza que debe asumir el usuario. Creo que ese es el poder de la palabra claveunsafe. De hecho, quizá debería haberse dividido en bloquestrust_mey funcionescheck_yourself.unsafelimita la conversación sobre seguridad de memoria a lugares muy acotados y auditables del código, y al mismo tiempo crea una conversación nueva y manejable sobre la confianza.use*para la API de hooks, pero me pregunto por qué en Dioxus la función que crea un signal nuevo se llamause_signal.let mut count = use_signal(|| 0);¿no es una llamada que crea un signal nuevo? El signal no se vuelve a crear en cada renderizado, y ese es el punto central de un signal.En SolidJS se crea un signal con createSignal, como
const [count, setCount] = createSignal(0), y eso es mucho más fácil de entender.Los nombres de API importan, porque los hooks de estado se comportan distinto y pueden generar la necesidad de complementos como
useMemo. Me pregunto si hay alguna razón para haber elegido el nombreuse_signalmás allá de que Dioxus quiera parecerse a React.Se parece más a Preact que a Solid.
Las optimizaciones incluyen separar las partes dinámicas de la UI en “diff bins” aparte, memoización por defecto y que los signals marquen implícitamente las propiedades como dirty/managed.