Utilizando React para Construir Interfaces de Usuario de Alto Rendimiento en Minecraft

Rate this content
Bookmark

Esta charla hablará brevemente sobre la historia de cómo Mojang Studios decidió utilizar estándares web y React para construir la nueva pila de interfaz de usuario para Minecraft (Edición Bedrock), los desafíos que enfrentamos en cuanto al rendimiento y cómo llegamos a una solución que nos permitió seguir escribiendo una interfaz de usuario declarativa, pero sin el DOM virtual.

25 min
25 Oct, 2021

Video Summary and Transcription

Esta charla presenta el uso de React y tecnologías web para construir interfaces de usuario en Minecraft. Se discuten los desafíos de incorporar nuevos desarrolladores a la tecnología actual y los beneficios de utilizar estándares abiertos. El orador explica el uso de Gameface, una solución para construir interfaces de usuario de juegos con React y Webpack. La charla también aborda la gestión del estado en un entorno de juego y el uso de facetas para la optimización del rendimiento. Concluye con una visión general de la marca Oryui y la disponibilidad de recursos en GitHub.

Available in English

1. Introducción al uso de React en Minecraft

Short description:

Bienvenido a Usar React para Construir Interfaces de Usuario de Juego Eficientes en Minecraft. Soy Paolo, líder técnico en Mojang Studios. Nuestro objetivo es cambiar cómo se construyen las interfaces de usuario en Minecraft mediante la introducción de un sistema de diseño. Ya hemos implementado la pantalla de logros basada en estándares web y React. Admitimos múltiples plataformas y tipos de entrada, incluyendo VR.

Bienvenido a Usar React para Construir Interfaces de Usuario de Juego Eficientes en Minecraft. Mi nombre es Paolo. Soy líder técnico en Mojang Studios aquí en Estocolmo. Y trabajo en un juego con el que probablemente estés familiarizado, que es Minecraft.

Soy parte de este fantástico equipo compuesto por artistas, diseñadores, desarrolladores de C++ y JavaScript, y un productor. Y nuestro objetivo principal es cambiar cómo se construyen las interfaces de usuario en Minecraft. Y lo estamos haciendo no solo cambiando la pila tecnológica, sino también introduciendo un sistema de diseño en el producto.

Estos son algunos de los componentes que tenemos, y es posible que los veas implementados en los próximos años. Y sí, ya estamos incluso en producción. Implementamos una pantalla el año pasado, que es la pantalla de logros. Entonces, si juegas a Minecraft Bedrock Edition en tu Xbox o PlayStation, probablemente hayas visto la pantalla. Y esta pantalla está completamente basada en estándares web, y está construida con React. Y estas son todas las plataformas que admitimos, que también es uno de los principales desafíos para nuestro proyecto. Así que necesitamos ejecutarnos en Xbox One, en PlayStation, en Switch. Tenemos Android, teléfonos y tabletas, iOS, teléfonos y tabletas, Windows 10, Mac OS, casi todas las plataformas en las que Minecraft se ejecuta. Y luego necesitamos admitirlas. Y eso no solo se trata de las capacidades del dispositivo, sino también de los diferentes tipos de entrada. Así que necesitamos admitir el tacto, el gamepad, todo tipo de cosas. Incluso se admite la realidad virtual (VR) en Minecraft.

2. Using Web Technologies for Minecraft UIs

Short description:

¿Por qué estamos utilizando tecnologías web para construir interfaces de usuario en Minecraft? Minecraft es un juego con motor personalizado y la interfaz de usuario se construye completamente internamente. Incorporar nuevos desarrolladores a la tecnología actual lleva mucho tiempo, por lo que queríamos una solución basada en estándares abiertos para una mejor mantenibilidad y una velocidad de iteración mejorada.

Pero, ¿por qué estamos utilizando tecnologías web o, mejor dicho, web standards para construir interfaces de usuario en Minecraft? Hay muchas razones. Y algunas de ellas las cubrí en esta charla previa que di en 2018. Así que si tienes curiosidad, también puedes echarle un vistazo. Pero si no quieres hacerlo, aquí tienes un resumen. Básicamente, Minecraft es un juego con motor personalizado. Por lo tanto, no utiliza algo como Unreal o Unity. Por lo tanto, la interfaz de usuario se construye completamente internamente, es completamente personalizada. Y actualmente eso ha sido un problema para nosotros, ya que cuando incorporamos nuevos desarrolladores, les lleva mucho tiempo acostumbrarse a la tecnología y descubrir cómo usarla. Y queríamos pasar a una solución que nos llevara a una mejor mantenibilidad y que nos permitiera incorporar a las personas de manera más fácil y también mejorar la velocidad de iteración. En resumen, queríamos crear algo basado en estándares abiertos de la W3C y aprovechar todas las excelentes herramientas que tiene el ecosistema de JavaScript.

3. Using Gameface for Minecraft UIs

Short description:

No solo estamos tomando Chromium y embebido en Minecraft. En cambio, estamos utilizando una solución llamada Gameface de Korean Labs. Gameface es un subconjunto de estándares web abiertos, construido para interfaces de usuario de juegos con un enfoque en el rendimiento. Es como un pequeño navegador que ejecuta interfaces de usuario construidas con React y Webpack. Los desarrolladores web que se unen a Mojang pueden ser productivos desde el primer día y contribuir a la interfaz de usuario del juego.

Pero, ¿cómo lo estamos haciendo? ¿Simplemente estamos tomando Chromium y embebido en Minecraft? Así que técnicamente podría ser una posibilidad, y hay algunos juegos que realmente hacen esto. Lo que estamos haciendo es algo diferente. Entonces hay una empresa llamada Korean Labs, y han estado desarrollando soluciones basadas en Chromium durante un tiempo, para interfaces de usuario de juegos. Pero, ya han construido otra solución que llaman Gameface, donde tomaron los standards que son abiertos de la web, y luego construyeron solo un subconjunto de ellos en algo que llaman Gameface. Entonces Gameface, podría considerarse como un pequeño navegador, diría yo. Si construyes una interfaz de usuario para Gameface, probablemente se ejecutará en Chrome o Firefox, pero podría no ser el caso si eliges una interfaz de usuario aleatoria que construyas en Firefox y la colocas en Gameface, podría no funcionar. Por ejemplo, tiene soporte para Flexbox, pero no tiene soporte para Floats. Y está construido con el objetivo principal de dirigirse a la interfaz de usuario del juego, por lo que performance es lo principal, es uno de los objetivos principales. Pero quitando Gameface de la ecuación, es una pila bastante estándar. Usamos React, usamos Webpack, hacemos pruebas unitarias con Jest. Entonces, si eres un desarrollador web que trabaja en una tienda hoy y te unes a Mojang, probablemente serás productivo desde el primer día y podrás contribuir con una interfaz de usuario para el juego, lo cual es bastante impresionante y es una experiencia muy diferente a la que tenemos hoy en el estudio.

4. State Management and Facets in Game Environment

Short description:

Antes de hablar sobre el rendimiento, vamos a entender cómo funciona la gestión del estado en un entorno de juego. En las aplicaciones web tradicionales, el estado se copia en el navegador, pero en un mundo de juego, el motor de juego C++ mantiene el estado. Minecraft sirve como un buen ejemplo. La interfaz de usuario muestra la salud, la saciedad y los elementos seleccionados, que pueden cambiar según la interacción del jugador. Nos referimos a estas porciones de datos como facetas. Las facetas son similares a los observables y proporcionan actualizaciones a medida que cambian los valores. El estado debe residir en el lado C++, creando una tienda global. Nos inspiramos en Recoil y Jotai para construir nuestra solución, RackFacet, con algunas diferencias. RackFacet es una colección de paquetes que incluye RackFacet Remote para la comunicación entre JavaScript y C++.

Pero antes de hablar sobre el rendimiento, que es lo principal que queremos discutir en esta presentación, primero debemos hablar sobre cómo funciona la gestión del estado y cómo es diferente cuando estamos en un entorno de juego.

Entonces, cuando miramos una aplicación web tradicional, podemos pensar en ello de la siguiente manera. Tenemos el navegador, por ejemplo, aquí tengo Firefox ejecutando la interfaz de usuario y tiene su propio tiempo de ejecución de JavaScript y luego tenemos, digamos, un servidor en Internet ejecutando Node.js y luego tenemos solicitudes y respuestas HTTP que regresan. Es una separación muy similar a solicitud-respuesta y luego tenemos una copia del estado en el navegador.

Cuando ingresamos a un mundo de juego, lo que generalmente tenemos es solo un solo proceso, ¿verdad? Tenemos el motor de JavaScript que sigue funcionando, que tendrá nuestro código React y nuestro código de interfaz de usuario allí, pero tenemos el motor de juego C++ justo allí y eso es lo que llamamos nuestro backend y generalmente es el titular del estado. Si quieres entender esto, es mejor mirar un ejemplo y un buen ejemplo es Minecraft.

Entonces, si miras esta pantalla, que es básicamente lo que ves si estás jugando el juego, este es el HUD. Vemos básicamente la información sobre cuánta salud tiene tu personaje, la saciedad porque Minecraft es un juego de supervivencia, por lo que si no comes, comienzas a morir de hambre y puedes morir. También vemos los elementos a los que tienes acceso en tu barra de acceso rápido, por lo que estos son elementos que puedes cambiar rápidamente usando el gamepad y qué elemento tienes seleccionado. Entonces aquí puedes ver que tenemos el primer elemento seleccionado, que es la espada, pero un jugador también puede, al interactuar con el juego, cambiar el elemento seleccionado para que sea la carne podrida y eso no solo afecta al juego en sí, sino que también debe reflejarse en la interfaz de usuario. Y el jugador también puede recibir daño, ¿verdad? Digamos que un monstruo viene y un creeper explota al lado del jugador, y luego necesitamos recibir algo de daño de salud y aquí la salud ha bajado a ocho. Entonces aquí podemos ver que tenemos como dos categorías de datos, dos grupos de datos. Y llamamos a esos facetas.

Las facetas son un término que acuñamos internamente en el estudio porque necesitábamos algo que no existía dentro de la base de código. Entonces no pudimos usar modelo, por ejemplo. Pero esto es más o menos lo que es. Es solo una porción de datos. Pero así, como facetas conceptualmente, son muy similares a un observable donde están disponibles a lo largo del tiempo. Nos suscribimos a una faceta, como digamos las estadísticas del jugador, y luego seguimos recibiendo actualizaciones sobre nuevos valores a medida que cambian, a medida que el jugador juega el juego, ¿verdad? En la parte inferior podemos ver cómo avanza el tiempo y el jugador pierde salud, tenemos un componente hipotético de salud del jugador que se actualiza con la cantidad de salud que tiene el jugador. Conceptualmente, lo que queremos es que el estado no viva en el lado de JavaScript, sino que debe vivir en el lado C++, que es nuestro backend, pero está viviendo justo allí dentro del mismo proceso. Queremos una especie de tienda global y esa tienda global es el lado C++ del juego. Y cuando pensamos en tiendas globales y miramos el ecosistema de JavaScript, hay un par de soluciones disponibles. Algunas de las más populares en estos días son Recoil o Jotai y son muy similares en esta moda donde tienes una tienda global. Y tomamos un enfoque muy similar a estas soluciones, y nos inspiramos en la API de Recoil para construir algo que se sienta muy familiar para que cualquier persona que venga al estudio pueda entender qué conceptos estamos tratando de implicar. Pero hay algunas diferencias, por supuesto, que vamos a revisar a continuación. Entonces, RackFacet es en realidad un paquete, una colección de paquetes. Tenemos muchos paquetes. La parte que se ocupa de la comunicación entre los bits de JavaScript y los bits de C++ lo llamamos RackFacet Remote. Y esa es la primera parte de la que voy a hablar ahora. Y supongo que lo primero que debemos ver es cómo definimos las facetas, ¿verdad?, las partes del estado que tenemos que se comparten entre el lado C++ y el lado de JavaScript.

5. Using Remote Facets and Performance Optimization

Short description:

Definimos el contrato de la API, usamos selectores para elegir facetas y las convertimos en estados de React. Nuestra solución requiere un proveedor para implementar la conexión de JavaScript a C++. Configuramos oyentes y emitimos eventos para acceder y notificar datos. Las suscripciones y las funciones de limpieza garantizan actualizaciones eficientes. React ya es rápido.

Y si observaste... Si usaste Recall.js, por ejemplo, en algún momento esto podría resultar un poco familiar. Lo único es que aquí estamos usando TypeScript. Entonces, lo primero con lo que comenzamos es definir el contrato de la API, que es solo una interfaz para este tipo de datos. Esto es algo con lo que generalmente hablamos con los desarrolladores de C++. Por ejemplo, decimos que queremos tener una salud que sea un número y queremos tener una saciedad que sea un número. Luego tenemos un identificador único. Y así es como, desde el lado de JavaScript, podemos solicitar una parte específica de datos al lado de C++. Luego tenemos la definición en sí, que es muy similar a un átomo en el lenguaje de Recall.js. Y luego también tenemos selectores, que nos permiten elegir la faceta completa y cortar solo una parte de ella, como una función de mapeo. Aquí estamos seleccionando, por ejemplo, solo el atributo de salud de toda la faceta de estadísticas.

Y cuando queremos consumirlo, también es muy familiar, solo tendríamos algunos ganchos adicionales y algunos nombres diferentes aquí. Pero básicamente necesitamos usar el gancho useRemoteFacet para suscribirnos a esta faceta remota, para iniciar y comenzar a escuchar los eventos. Luego lo convertimos en un estado de React, que es la salud, que será la cadena real que contiene la salud, y luego simplemente podemos representar el resultado como un componente normal de React. La diferencia clave entre nuestra solución y las soluciones existentes en el espacio de código abierto es la suscripción. Nuestras facetas realmente no tienen ningún valor hasta que comenzamos a suscribirnos a ellas. Y después de eso, actúan prácticamente como observables. Entonces, en nuestra solución, debemos tener un proveedor que envuelva la aplicación y este proveedor tiene la responsabilidad de implementar la conexión desde el lado de JavaScript al lado de C++. En este caso, tenemos un motor, que es como un objeto global al que tenemos acceso. Es algo así como un emisor de eventos, donde desde el lado de C++, desde el lado de JavaScript, necesito configurar un oyente, que en este caso está escuchando el evento facet-updated player stats. Digamos que quiero acceder a los datos de las estadísticas del jugador. Luego necesito emitir un evento para notificar al lado de C++ o al motor del juego que estoy interesado en esos datos. Y finalmente, puedo devolver una función que puede realizar una limpieza. Entonces, lo que sucede en la práctica es que cuando un componente se suscribe, digamos, al selector de salud del jugador que mostramos en el ejemplo anterior, si es la primera vez que se llama a esta función, configuraremos la suscripción y comenzaremos a escuchar esos datos. Y una vez que ese componente se desmonta, se llama a la función de limpieza y dejamos de escucharlo. Le decimos al lado de C++ que deje de notificarnos las actualizaciones. Eso es bastante genial. Y funciona muy bien para nosotros.

Entonces, el siguiente paso, que es la parte interesante para todos ustedes, es, por supuesto, cómo manejamos el rendimiento. ¿Dónde optimizamos las cosas para que funcionen bien en el desarrollo de juegos? Y creo que lo primero que debemos dejar claro es que React por sí solo ya es bastante rápido.

6. Optimizando la Conciliación de React con Actualizaciones de Facetas

Short description:

Cuando construimos aplicaciones web con React, a menudo tratamos de evitar renderizaciones innecesarias y mejorar el rendimiento. En este caso, proponemos omitir la conciliación de React actualizando directamente el DOM a partir de las actualizaciones de facetas. Demostramos este enfoque con un ejemplo de una barra de progreso. Para lograr esto, nos suscribimos a las facetas utilizando el gancho useRemoteFacet y transformamos el valor de la faceta utilizando el gancho useFacetMap. Sin embargo, al pasar el valor transformado al div, React puede no reconocer el tipo de datos.

Si estás construyendo aplicaciones web, generalmente es suficiente usar simplemente React tal como está. Y soluciones como Recoil o Jotite, ayudan a reducir y seguir las actualizaciones para que solo se actualicen partes específicas de tu árbol de React. Y cuando nos encontramos con problemas de rendimiento en React, generalmente se recomienda que revisemos nuestros componentes y veamos si estamos realizando alguna renderización innecesaria y si podemos evitarla a toda costa.

Entonces, cuando miramos este concepto, es como, ¿qué pasaría si en lugar de simplemente evitar renderizaciones innecesarias, pudiéramos evitar todas las renderizaciones por completo? ¿O podríamos tener una situación en la que básicamente no activemos la conciliación de React? Así es como sucede en nuestro ejemplo anterior, ¿verdad? La faceta se actualiza a través de un evento desde el lado de C++ que activa, que a su vez actualiza algún estado internamente en React, lo que activa la conciliación y luego React, a través del DOM virtual, descubre que necesita actualizar este nodo de texto y así se produce una actualización. Lo que estamos proponiendo es que podríamos simplemente omitir al intermediario y pasar directamente de la actualización de la faceta a la actualización del DOM. Entonces, si volvemos al ejemplo que teníamos antes, lo que estamos proponiendo es en lugar de tomar la faceta, que es como esta estructura de datos agradable que contiene un valor a lo largo del tiempo, en lugar de desempaquetarla y convertirla en un estado de React, ¿podemos simplemente tomar la faceta y pasarla directamente a la renderización de React y dejar que React se encargue de desempaquetar el valor de la faceta? Y eso es exactamente lo que hicimos. Queremos pasar la faceta y eso actualiza directamente un nodo de texto. Veamos cómo lo hemos hecho. Tomando el ejemplo anterior, lo amplié un poco y lo hice un poco más interesante. Aquí tengo ahora una barra de progreso un poco más compleja. Estoy representando algunos divs para darle un estilo agradable. Puedes ver en la parte superior cómo se verá visualmente. Y luego vemos el resultado codificado. Tenemos una variable codificada allí con el progreso establecido en dos. Así que ese es un componente React muy simple, simplemente representando una barra de progreso. Entonces, si quieres tomar este ejemplo y hacer que omita por completo la conciliación, ¿cómo podríamos hacer eso? Creo que el primer paso, por supuesto, es suscribirnos a las facetas en el primer paso. Cambiamos eso para usar el gancho useRemoteFacet, para tomar el valor del selector y capturarlo para usarlo en un componente. Pero el progreso aquí en realidad no es un número en sí, en realidad es solo la faceta, es una estructura de datos que contiene el valor en su interior. Así que en realidad estoy obteniendo un error tipográfico aquí porque no puedo realizar una operación aritmética con una faceta. No es un número. Entonces, ahora necesitamos encontrar una forma de, vale, tengo esta faceta y quiero hacer alguna transformación en ella y convertirla en algo más. Si esto fuera un Recoil en un estado global, probablemente solo usaría un selector. Dado que esto está dentro de un componente React, lo que necesitamos es alguna forma de crear un selector que esté definido dentro de un componente React. Y admitimos eso a través de un gancho personalizado que tenemos llamado useFacetMap, y es muy similar a un selector conceptualmente. Toma una faceta de entrada, en realidad puedes tomar varias, pero en este caso solo estamos pasando una, que es el progreso al que nos suscribimos en la línea anterior. Luego tenemos una función de mapeo que tomará el progreso, que es el número, proveniente de la faceta, y lo transformará en una cadena que contiene la unidad de píxeles. Y luego el resultado de eso también es otra faceta, que ahora contiene el ancho en la variable. El siguiente paso ahora, por supuesto, es tomar este ancho y pasarlo al div. Pero si hacemos eso, React no estará contento. Dirá, hey, no sé qué hacer con este tipo de datos, ¿verdad? Estás tratando de darme algo que no es una cadena, no es un número.

7. Renderizado con FastDiv y Facetas

Short description:

Introdujimos un nuevo div llamado FastDiv y creamos una serie de componentes que aceptan facetas como props. Esto nos permite crear un componente que se suscribe a una faceta remota y la mapea a una faceta de ancho. Hemos creado un renderizador que admite facetas como valores para props e incluso puede crear componentes personalizados que admiten nativamente facetas.

No sé cómo renderizar esto. Entonces, el siguiente paso en esto es que necesitamos cambiar el propio renderizador de React para admitir este tipo de data. Y eso es lo que hicimos, al introducir un nuevo div que llamamos FastDiv. Y en realidad creamos toda una serie de componentes que coinciden, como uno a uno. Entonces tenemos un FastB, un FastSpan. En lugar de aceptar solo números regulares, cadenas para los props, también aceptan facetas como prop. Y al final, lo que tenemos básicamente es esto, ¿verdad? Un componente que se suscribe a una faceta remota, convirtiéndola en una variable de progreso que contiene una faceta de progreso. Luego mapeamos eso en una faceta de Ancho que tiene el ancho. Y luego tomo eso y lo paso al FastDiff que actualiza ese prop en el DOM. Básicamente hemos creado un renderizador que admite nativamente facetas, o podrías decir un observable ligero, como valores para los props. También podríamos ir un paso más allá y crear componentes personalizados que también admitan nativamente facetas como valor.

8. Using Facets for Improved Performance

Short description:

Veamos cómo el uso de facetas mejora el rendimiento. Al extraer el componente de la barra de progreso y pasar el progreso como una faceta, evitamos activar renders innecesarios. La implementación detrás de escena utiliza un renderizado personalizado y está disponible en el paquete react-facet-dom-fiber. Las pruebas de rendimiento en Xbox One y Chrome muestran que la solución basada en facetas es significativamente más rápida, tardando solo el 32% del tiempo en comparación con la implementación de React basada en estado.

Veamos cómo se verá eso. Si volvemos atrás y echamos un vistazo a este ejemplo de la salud del jugador, ¿qué pasa si también queremos hacer la plenitud? Queremos renderizar también la barra de progreso de la plenitud. ¿Podríamos hacer eso? Supongo que lo primero que queremos hacer es extraer los componentes para que podamos reutilizarlos en ambos lugares. Queremos tomar esta parte aquí que maneja la barra de progreso y extraerla a un componente de barra de progreso. Pero queremos pasar el progreso como una faceta. No queremos pasar un número. Porque si desempaquetáramos eso en la salud del jugador para convertirlo en un estado regular de React, volveríamos básicamente a activar la conciliación, y perderíamos todos los beneficios que estábamos tratando de lograr.

Aquí los tenemos, básicamente la salud del jugador y la plenitud del jugador, dos componentes que usan la barra de progreso, y ambos pasan un progreso, cada uno con su propia faceta que contiene sus propios data. Y la implementación de la barra de progreso se ve así. En lugar de tomar un progreso que es solo un número, en su lugar toma una faceta de un número. Y tenemos el tipo específicamente disponible allí. Pero por lo demás, la implementación aquí en el cuerpo es exactamente la misma que teníamos antes. Entonces esto es más o menos lo que está sucediendo al final. Tenemos en la parte superior nuestra faceta remota de estadísticas del jugador. Una vez que se notifica una actualización desde el lado de C++, ese data se pasa hacia abajo al selector remoto de salud del jugador que luego selecciona solo la salud del data. Eso luego se pasa a su faceta remota de uso, que activa la suscripción. Luego pasa por el mapa de facetas de uso que lo transforma. Y luego, de esa manera, finalmente llega a la faceta div y luego se actualiza el DOM. Y lo genial de todo esto es que todo esto sucede detrás de escena. No estamos activando ningún renderizado envuelto en absoluto. Y toda esta implementación está construida como un renderizado personalizado, como dije, y está disponible en este paquete, react-facet-dom-fiber.

Pero todo esto es fantástico y es bastante genial, pero ¿qué tan bien, cuánto mejora realmente el rendimiento? Entonces, comparando, y puse aquí dos plataformas diferentes solo para darle algo de perspectiva. Estoy ejecutando estos escenarios tanto en una Xbox One como en Chrome. Esta Xbox One está ejecutando el juego de Minecraft, y también tenemos Chrome en mi MacBook. Este ejemplo que estoy mostrando aquí básicamente toma la implementación de la barra de progreso que hicimos antes y simplemente cambia su valor en cada fotograma y veo cuánto tiempo estoy tomando entre cada implementación. A la izquierda, tenemos una implementación basada en estado de React y toma el 100% del tiempo. Y en la Xbox One, podemos ver que una solución basada en facetas solo toma el 32% del tiempo para hacer el mismo trabajo. Cuando miramos Chrome, la diferencia es un poco menor, pero también es mucho más rápido cuando miramos la implementación de las facetas. Otro escenario muy interesante para analizar es imaginar si tienes una lista grande y la estás ejecutando a través de una serie de componentes y la estás memorizando. Entonces cada componente está memorizado.

9. Comparación de rendimiento con Facetas

Short description:

Cuando comparamos la solución basada en Facetas en la Xbox con la implementación estándar de React, la diferencia es enorme, con la Xbox siendo significativamente más rápida. Plataformas como Xbox, PlayStation y Switch, que no tienen JIT habilitado, pueden tener características de rendimiento diferentes. Cuanto más complejos se vuelven los árboles de React, mayor es la brecha de rendimiento. Más información y ejemplos están disponibles en nuestro repositorio de GitHub.

Cuando observamos la solución basada en Facetas en la Xbox, la diferencia se vuelve enorme, tomando solo el 12% del tiempo. Y en Chrome, también es aproximadamente el 30% del tiempo. Este ejemplo que mencioné es interesante de analizar si tenemos una lista grande, pero todos los elementos se actualizan al mismo tiempo, aquí podemos ver que la Xbox es en realidad mucho más rápida en comparación con la implementación estándar de React. Cuando observé Chrome en mi MacBook, la diferencia no es tan grande. Y lo principal que vale la pena mencionar es que cuando ejecutamos V8 en Chrome, en nuestras Macs, tenemos compilación en tiempo real. Pero desafortunadamente, en algunas plataformas como Xbox, PlayStation y Switch, no podemos tener JIT habilitado. Por lo tanto, las optimizaciones y bibliotecas a las que estamos acostumbrados se comportarán y tendrán diferentes características de rendimiento cuando las ejecutemos. Además, otra cosa importante es que cuanto más complejos se vuelven los árboles de React, entonces mayor será la brecha y más rápida será la implementación en relación con la implementación estándar de React. Tenemos más data disponible en nuestro repositorio de GitHub. Todos los ejemplos que mencioné están allí y puedes ver sus implementaciones reales para comprender mejor lo que hacen. No tengo mucho tiempo para entrar en detalles aquí, pero todo eso está disponible en el repositorio de GitHub.

10. Introducción a Facetas y Oryui

Short description:

Las Facetas proporcionan una API más amigable para React con hooks que aceptan y devuelven facetas. El paquete react-facet-core incluye estos hooks, como useFacetState y useFacetCallback. Las Facetas son un conjunto de bibliotecas, que incluyen el tipo de datos observable ligero y el paquete remoto para compartir estado entre JavaScript y C++. También tenemos un renderizador personalizado dentro de DOM fiber. Comenzar con las Facetas es fácil utilizando el paquete de componentes DOM, que implementa componentes rápidos como componentes regulares de React. Estamos compartiendo el código bajo la marca Oryui y tenemos emocionantes posiciones abiertas en Mojang. Visita nuestro repositorio de GitHub para obtener más información.

Pero no solo eso, quiero decir, si observas las facetas, tenemos almacenes globales, en realidad tenemos una serie de hooks más que se convierten en una API mucho más amigable para React. Para todos los hooks de React que se encuentran aquí a la derecha, como useState, useReduce o useEffect, tenemos implementaciones correspondientes en el mundo de las facetas, pero en lugar de, ya sabes, la diferencia es que en realidad puede aceptar facetas como entrada y pueden devolver una faceta como salida. Todo esto está disponible en el paquete react-facet-core.

Solo para ir rápido, así es como se ve, donde tengo este componente aquí, donde estoy usando useFacetState, que es muy similar a useState, pero en lugar de que el valor sea solo una cadena, podría ser, por ejemplo, una faceta de una cadena. Luego también tengo useFacetCallback aquí, que es muy similar a useCallback, pero en lugar de eso te permite pasar un valor que es una faceta. También hay más hooks y documentación disponibles en nuestra página de GitHub.

En resumen, una faceta no es solo una biblioteca, sino un conjunto de bibliotecas. Tenemos el nuevo tipo de datos que introdujimos, que llamamos facetas, por supuesto, que es un observable ligero que vive dentro del núcleo de facetas de React, y puedes usar solo el núcleo de facetas de React para construir algo sin necesidad de usar el renderizador personalizado o cualquier otra cosa o el paquete remoto. Tenemos el paquete remoto, que es el mecanismo que desarrollamos para tener este estado de almacenamiento global para compartir el estado entre el lado de JavaScript y el lado de C++, y tenemos nuestro renderizador personalizado que construimos dentro de DOM fiber. Estos son todos los paquetes que tenemos, y puedes consultar la documentación para averiguar qué hacen. No tengo mucho tiempo en la charla para revisarlos.

Pero parece un poco desalentador, pero en realidad es bastante fácil comenzar si quieres probar las facetas. Tenemos un paquete llamado componentes DOM. Lo que te permite hacer es implementar estos componentes rápidos que creamos, pero en lugar de ser componentes de host en un renderizador personalizado de React, en realidad son solo componentes regulares de React. Aquí puedes ver cómo se usan en un DOM de React regular para renderizar este componente. Todo esto se está compartiendo como código abierto. Estamos compartiendo bajo la marca Oryui. Oryui es una especie de iniciativa que estamos llevando a cabo en Mojang Studios para tratar de estandarizar el desarrollo de interfaces de usuario en la industria de los videojuegos. Entonces, lo que estamos haciendo es intentar impulsar eso. Oryui tendrá facetas de React para comenzar, pero también lanzaremos otros paquetes que estamos desarrollando. Este es el fantástico logotipo. Y este es nuestro repositorio de GitHub. Si quieres ver más rápido el código base, si quieres obtener más información, ve a GitHub y echa un vistazo a Mojang/Oryui. Y, por supuesto, tengo que mencionar que estamos contratando en Mojang. Es un proyecto bastante emocionante. Quiero decir, no en todas partes puedes usar tus habilidades web para contribuir a uno de los juegos más grandes del mundo. Es bastante emocionante poder trabajar aquí. Y si quieres hacerlo, tenemos posiciones abiertas para líderes técnicos, desarrolladores web. No dudes en comunicarte conmigo o ir directamente a jobsmojang.com. Muchas gracias. Tuve que correr un poco a través de las diapositivas, pero sí, si tienes alguna pregunta, creo que pronto tendremos una sesión de preguntas y respuestas. Muchas gracias y no dudes en comunicarte conmigo si tienes alguna pregunta. Adiós.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2022React Advanced Conference 2022
25 min
A Guide to React Rendering Behavior
Top Content
React is a library for "rendering" UI from components, but many users find themselves confused about how React rendering actually works. What do terms like "rendering", "reconciliation", "Fibers", and "committing" actually mean? When do renders happen? How does Context affect rendering, and how do libraries like Redux cause updates? In this talk, we'll clear up the confusion and provide a solid foundation for understanding when, why, and how React renders. We'll look at: - What "rendering" actually is - How React queues renders and the standard rendering behavior - How keys and component types are used in rendering - Techniques for optimizing render performance - How context usage affects rendering behavior| - How external libraries tie into React rendering
React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Building Better Websites with Remix
Top Content
Remix is a new web framework from the creators of React Router that helps you build better, faster websites through a solid understanding of web fundamentals. Remix takes care of the heavy lifting like server rendering, code splitting, prefetching, and navigation and leaves you with the fun part: building something awesome!
React Advanced Conference 2023React Advanced Conference 2023
33 min
React Compiler - Understanding Idiomatic React (React Forget)
React provides a contract to developers- uphold certain rules, and React can efficiently and correctly update the UI. In this talk we'll explore these rules in depth, understanding the reasoning behind them and how they unlock new directions such as automatic memoization. 
React Advanced Conference 2022React Advanced Conference 2022
30 min
Using useEffect Effectively
Top Content
Can useEffect affect your codebase negatively? From fetching data to fighting with imperative APIs, side effects are one of the biggest sources of frustration in web app development. And let’s be honest, putting everything in useEffect hooks doesn’t help much. In this talk, we'll demystify the useEffect hook and get a better understanding of when (and when not) to use it, as well as discover how declarative effects can make effect management more maintainable in even the most complex React apps.
React Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Top Content
Concurrent React and Server Components are changing the way we think about routing, rendering, and fetching in web applications. Next.js recently shared part of its vision to help developers adopt these new React features and take advantage of the benefits they unlock.In this talk, we’ll explore the past, present and future of routing in front-end applications and discuss how new features in React and Next.js can help us architect more performant and feature-rich applications.
React Advanced Conference 2021React Advanced Conference 2021
27 min
(Easier) Interactive Data Visualization in React
Top Content
If you’re building a dashboard, analytics platform, or any web app where you need to give your users insight into their data, you need beautiful, custom, interactive data visualizations in your React app. But building visualizations hand with a low-level library like D3 can be a huge headache, involving lots of wheel-reinventing. In this talk, we’ll see how data viz development can get so much easier thanks to tools like Plot, a high-level dataviz library for quick & easy charting, and Observable, a reactive dataviz prototyping environment, both from the creator of D3. Through live coding examples we’ll explore how React refs let us delegate DOM manipulation for our data visualizations, and how Observable’s embedding functionality lets us easily repurpose community-built visualizations for our own data & use cases. By the end of this talk we’ll know how to get a beautiful, customized, interactive data visualization into our apps with a fraction of the time & effort!

Workshops on related topic

React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Featured WorkshopFree
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React Advanced Conference 2021React Advanced Conference 2021
132 min
Concurrent Rendering Adventures in React 18
Top Content
Featured WorkshopFree
With the release of React 18 we finally get the long awaited concurrent rendering. But how is that going to affect your application? What are the benefits of concurrent rendering in React? What do you need to do to switch to concurrent rendering when you upgrade to React 18? And what if you don’t want or can’t use concurrent rendering yet?

There are some behavior changes you need to be aware of! In this workshop we will cover all of those subjects and more.

Join me with your laptop in this interactive workshop. You will see how easy it is to switch to concurrent rendering in your React application. You will learn all about concurrent rendering, SuspenseList, the startTransition API and more.
React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Top Content
Featured Workshop
The addition of the hooks API to React was quite a major change. Before hooks most components had to be class based. Now, with hooks, these are often much simpler functional components. Hooks can be really simple to use. Almost deceptively simple. Because there are still plenty of ways you can mess up with hooks. And it often turns out there are many ways where you can improve your components a better understanding of how each React hook can be used.You will learn all about the pros and cons of the various hooks. You will learn when to use useState() versus useReducer(). We will look at using useContext() efficiently. You will see when to use useLayoutEffect() and when useEffect() is better.
React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
React Advanced Conference 2021React Advanced Conference 2021
145 min
Web3 Workshop - Building Your First Dapp
Top Content
Featured WorkshopFree
In this workshop, you'll learn how to build your first full stack dapp on the Ethereum blockchain, reading and writing data to the network, and connecting a front end application to the contract you've deployed. By the end of the workshop, you'll understand how to set up a full stack development environment, run a local node, and interact with any smart contract using React, HardHat, and Ethers.js.
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Featured Workshop
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn