Y por qué su arquitectura es impresionante, al más alto nivel.
React Native a menudo se presenta como un cambio de juego que permite ejecutar código JavaScript dentro de un entorno móvil. Su principal fortaleza es que no se basa en vistas web como otros competidores ( Phonegap , Ionic , Cordova …), sino en los materiales reales proporcionados por las diferentes plataformas. Tiene acceso incorporado a todas las vistas y componentes nativos, y a aproximadamente 70 API de dispositivos específicos de forma predeterminada ( puede ampliarlo ).
Al escribir aplicaciones React Native, construimos interfaces de usuario nativas. Y ese es el punto clave, creamos instancias UIView
tal como lo haríamos con los lenguajes específicos de la plataforma:
Mi primera suposición sobre este marco fue algo así como:
Probablemente crean un AST a partir del código JS y lo transforman para que se ejecute en varios dispositivos.
Eso tendría sentido y eso es lo que hace G oogle/Flutter al crear aplicaciones (con Dartlang ). Pero esa no es la forma React Native.
El principal problema con este enfoque es que apuntar a plataformas para la compilación basada en código JavaScript implicaría la creación de nuevos compiladores. No conozco ninguna herramienta existente que acepte JavaScript como código de entrada que pueda producir código para cada plataforma específica ( eventualmente, vea Jasonette ).
NB: algunos lo han intentado pero solo para el desarrollo móvil con enfoques obstinados
Pero lo que existen actualmente son compiladores que apuntan a su propia plataforma específica. Por ejemplo, tenemos compiladores que aceptan código Java/Kotlin y apuntan a la plataforma Android, u Obj-C/Swift que apuntan a la plataforma iOS. Existen muchos compiladores para diferentes lenguajes y destinos. Hacen bien su trabajo porque han sido diseñados para crear artefactos optimizados para ellos.
React Native está construido de tal manera que utiliza compiladores existentes:
Está construido con una arquitectura realmente abierta que permite ejecutar el código, no solo en dispositivos móviles, sino también en otras plataformas:
También se puede utilizar con otros marcos:
Entonces, ¿cómo creó el equipo un marco de este tipo, que es independiente de la plataforma y el marco, utilizando las herramientas y los compiladores existentes?
Demos un paso atrás y veamos el panorama general de React Native.
React Native trata con dos reinos, el de JavaScript y el nativo. Ambos pueden compartir información. Se comunican mediante un "puente", que definitivamente es el corazón de la arquitectura React Native, la parte que ofrece tanta flexibilidad.
El puente es el concepto que proporciona una forma de comunicación bidireccional y asíncrona entre estos dos universos. Lo importante aquí es que están completamente escritos en diferentes tecnologías, pero pueden comunicarse.
Los subprocesos JS se comunican con los nativos a través del puente.
Recordemos cuando codificábamos aplicaciones backend distribuidas con comunicaciones multiservicio.
¿Cómo gestionamos la comunicación entre dos servicios que son completamente diferentes a nivel de idioma/plataforma?
Utilizamos lenguajes interoperables, como JSON o XML, y nos apoyamos en protocolos asíncronos como AMQP (o cualquier otro).
Comunicaciones bidireccionales entre servicios heterogéneos
Si queremos que estos dos servicios se comuniquen, dependemos de una cola de mensajes. El primer servicio empuja algunos comandos dentro de la cola y el otro tiene que ejecutar estos comandos cuando sea posible .
React Native se comporta de la misma manera. El reino de JavaScript envía mensajes JSON asíncronos que describen la acción que se supone que debe realizar la parte nativa.
Por ejemplo, el lado de JavaScript enviará información sobre las vistas que debe crear el lado nativo. Cuando el lado nativo esté listo, creará efectivamente las vistas:
JavaScript envía comandos de forma asíncrona al lado nativo para la gestión de vistas, con JSON
En React Native, el puente respalda el rol de intermediario de mensajes, manejando comandos asincrónicos entre los dos mundos diferentes.
Ofrece múltiples posibilidades:
Cuanto más ubicuo y universal sea el lenguaje del puente, mayores serán las posibilidades... ¡y de hecho lo son !
Incorpora el marco Apple JavaScriptCore , que expone las API para acceder a las capacidades reales de JavacriptCore VM. Mucha gente usa estas API en el mundo de Obj-C y Swift. Pero hay una API de C, y la de Obj-C es en realidad solo un contenedor.
Con esto en mente, el código JavaScript se puede ejecutar dentro de un programa C/C++. Puede inyectar variables, funciones y declarar globales para mejorar el código JavaScript existente. React Native se basa en este tipo de magia para hacer que JavaScript se comunique con el mundo nativo y, por lo tanto, active acciones en el mundo C/C++.
Inyectar cosas dentro del código JavaScript también significa que el código C/C++ puede ejecutar funciones.
Este diagrama resume rápidamente cómo el mundo de JavaScript puede lidiar con el de C/C++:
El código JS es administrado por el marco JSCore
La comunicación en el lado nativo es la parte “más fácil”.
Comencemos con la plataforma iOS. Dado que Obj-C es una extensión del lenguaje C, puede comunicarse con él de forma nativa. De esta forma, los intercambios entre el puente y el mundo Swift/Obj-C son fáciles y naturales.
Diagrama de alto nivel de JS interactuando con el mundo de iOS
En Android, debemos confiar en la interfaz nativa de Java para dialogar con el puente.
Diagrama de alto nivel de JS interactuando con el mundo de Android
Aquí hay una publicación antigua pero realmente impresionante y profunda que explica cómo Tadeu Zagallo implementa el puente en iOS .
Avíseme si tiene más preguntas sobre los componentes internos de React Native. Trataré de aportar todo lo que sé sobre el tema.