React Native is an excellent cross-platform mobile app solution that lets you easily create Native mobile apps using React (and JavaScript). React Native requires the use of JavaScript engines to execute JavaScript code, including JavaScriptCore, Hermes, and V8.

With the rise of new frameworks such as the Flutter, React Native is experiencing increased challenges and RN performance bottlenecks are becoming more apparent. In order to remain competitive against frameworks like the Flutter, the RN also underwent a very big upgrade in architecture.

Existing structure and problems

  1. React code written by the user
  2. React code after conversion js
  3. The Bridge
  4. Native side

The biggest problem with the original architecture:

  • The component and APIToo much reliance on JSBridge initializationAnd communication is limited to this channel.
  • JS and Native don’t really communicate directly with each other, their communication depends onAsynchronous JSON messages transmitted across the Bridge.

The information passed between them should be serialized as JSON and transferred asynchronously. This creates a common performance problem, such as a blank screen when quickly swiping the ListView. Because of the asynchronous nature of JSBridge, the shadow layer is rendered asynchronously to the native UI, and a large number of UI events will block on JSBridge if it slides too fast.

UI rendering process is divided into three layers: JS business layer, Shadow Tree, native UI layer.

JS layer will generate a string of JSON data for all UI nodes and pass it to the native shadow layer. Native Shadow layer will pass the node data into the native shadow layer. Add a new UI or remove some unneeded UI components.

From the rendering level, React Native is run by multiple threads. The most common ones are JS threads and Native threads. Once there is an exception between the threads, JSBridge will block as a whole.

New architecture and solutions

RN replaced the previous JSBridge with JSI in version 0.59.

The new architecture divides the Bridge into two parts:

  • Fabric, the UI Manager for the new architecture
  • TurboModules, a new generation of implementations that interact with the native side

JSI is a streamlined, general-purpose JS engine interface that can, in theory, interconnect with any JS engine, including Google’s V8 and Microsoft’s ChakraCore, or a new version of JavaScriptCore (JSC) that RN currently uses (JSI has been integrated into RN version 0.59). And the JSC version was upgraded in this release).

Core advantages of the new architecture:

  • JSI is a bridge between JS and Native by implementing a JSI::HostObject in the C++ layer, nowYou don't need to serialize to JSONAnd two-way transmission and a series of operations,The direct synchronous communication between Native and JS is realized.

Using JSI,Fabric exposes UI operations to JavaScript as functions, and the new Shadow Tree (which determines what is actually displayed on the screen) is shared between the two realms, allowing both sides to interact directly.

UI rendering in the new architecture and how to solve the white screen problem during the fast slide (solid lines are synchronous, dashed lines are asynchronous) :

  1. Initialization: the JS to Shadow layer is already synchronous, while the Shadow layer to native UI can be asynchronous or synchronous, and components can adapt different operations according to their business scenario.
  2. Sliding process: the native side directly controls the JS layer rendering, while creating the shadow layer node node. The node node will render the native UI in a synchronous manner. The whole process of sliding rendering is synchronous, so there will be no white screen problems under the old architecture.

Another advantage of JSI is that it smoothes out the differences between JavaScript engines. With JSI, we don’t have to care whether the underlying engine is Hermes or JavaScriptCore, the underlying JSI is digested. Therefore, you only need to write based on the JSI interface.

JS engine

When using React Native, your JavaScript code will run on two different environments:

  • On iOS, Android emulators, or real phones, React Native usesJavaScriptCore, which is the JavaScript engine used by Safari. However, JavaScriptCore does not use just-in-time compilation (JIT) technology on iOS, because in iOS applications do not have writable or executable pages of memory (and therefore cannot dynamically generate code).
  • When debugging with Chrome, all the JavaScript code runs in Chrome and communicates with the native code via WebSocket. The runtime environment isV8 engine.
  • Facebook has launched a new generation of JavaScript execution engine Hermes.HermesIs a small, lightweight JavaScript engine optimized for running React Native on Android.

For many applications, simply enabling Hermes reduces startup time, memory usage, and application size, and because it is implemented as a JavaScript standard, it is easy to integrate into React Native applications.

To open Hermes, first make sure you’re using at least React Native 0.60.2 or higher.

Edit the Android /app/build.gradle file and make the following changes:

  project.ext.react = [
      entryFile: "index.js",
-     enableHermes: false  // clean and rebuild if changing
+     enableHermes: true  // clean and rebuild if changing
  ]
Copy the code