By Chen Feldman

Release Date: 2019.07.30

Original link: medium.com/swlh/react-…

Part of the translation is free translation.

React Native has become one of the most popular mobile App development frameworks in recent years. Solves the question that many developers often think about: should you use a native development client app or a Web development Hybird app?

Developing with RN requires web knowledge and React experience, as it is based on the React framework. It’s a little harder than using a library like Cordova directly, but a lot easier than writing native client code for Swift and Kotlin. RN can get a performance experience similar to native by writing pure JS code.

Part 1: What dark magic is RN’s Bridge?

Before we get started, let’s talk about how React Native positions itself compared to other solutions.

From left to right, there are three camps:

  1. Native Native. This means you want to develop your App in a native language, such as Swift for ios or Kotlin for Android. You’re guaranteed to get the best performance and take full advantage of the device hardware and native apis. However, this requires learning two different programming languages, maintaining two sets of code, and possibly having twice as many bugs, and even having two different development teams.

  2. Hybrid. If you are a Web developer or have a web team that is already familiar with JS, HTML, CSS, and some front-end libraries, you can choose this solution and use Cordova/Ionic to make your web pages mobile apps. There is only one technology stack to learn, but there are limitations in performance, hardware, and API usage.

  3. Class native (actually a Hybrid). React Native falls into this category, and in theory all developers need is Web development knowledge. But the learning curve is a little bit higher than Hybrid. Developers need to learn how to use React Native’s library. In some scenarios, you may also need to open the project using XCode or Android Studio. However, the code can be written for both iOS and Android, and the development constraints are less than those of Hybrid. Performance will be more like native development, and some native apis will be easier to use.

Now that we understand RN’s positioning, let’s compare RN’s rendering to Hybrid’s:

As you can see from the figure above, apps that use Cordova are stored in webView. It’s more like a browser in an App. In web terms, this is more like an iFrame in a Web app.

The left side shows how React Native is formed. Each component in RN, such as Text, Button, Image, etc., has a corresponding Native component. So unlike what many developers new to RN might think, RN does not compile to native code, it does a mapping between JS components and native components.

When we write an RN component in the Render function like this:

The pre-written native component in the back would look like this:

If we use iOS as an example, here’s the native component code in RN:

In general, the RN team has created and mapped all the native components for us. All we need to do is write JavaScript code based on RN components and libraries. The rest is invisible to the average developer, like black magic.

So, it looks like all we have to do is write JS code. Let’s explain what the architecture looks like step by step. Bridge is the best place to start:

RN can be divided into JS and Native parts, both of which have their own threads

Thread communication is via Bridge, which transmits JSON information, including module ID, Method ID, and some required data. The two sides are not directly aware of each other, nor do they share the same memory.

It’s a bit like communication between different servers. If you have backend services written in different languages, how do you communicate between them?

Many people think queues are a good solution. You send JSON/XML queue messages that conform to the corresponding protocol, and each service knows how to read and parse them into the corresponding data and behavior. This queue is just like a Bridge in RN.

Here is an example of how communication works, where information is sent to the Bridge. From creating new views and styles and displaying them on the screen, to setting up child components on the mobile and doing some things:

If you want to see Bridge messages in the console, simply place the following code snippet in index.< platform >.js

Now that we know how RN communicates, we’re beginning to reveal the dark magic.

  • Communication between JS code and Objective-C. RN uses built-in JSCore on ios, but requires an extra Js engine to compile on Android
  • JS engines know how to convert JS to machine language more efficiently.

This is why Android apps take more time to load because you need to load JSCore into your project. However, after 0.60.2 RN can use Hermes, which is a better JS engine for RN.

Part 2: How does Bridge work?

In this section, we will analyze the process from clicking the App icon to opening the App and some of the related details.

To understand how RN creates views behind the scenes, we need to explain some basic concepts:

  1. UIManager: On the Native side, it is the main running thread in iOS/Android. Only it has permission to modify the client UI.
  2. JS Thread: Runs the packaged main.bundle. JS file, which contains all of RN’s business logic, behavior, and components.
  3. Shadow Node/Tree: a component Tree in the Native layer, which helps to monitor UI changes in the App, similar to the relationship between virtual Dom and Dom in ReactJS.
  4. Yoga: Used to calculate the layout. Is a C engine written by Facebook to convert flexbox-based layouts to Native layouts.

With some basic concepts in mind, let’s take a look at what happens at each step of opening the App:

  1. The user clicks on the App icon

  2. UIManager thread: Load all Native libraries and Native components such as Text, Button, Image, etc

  3. Tell the Js thread that the Native part is ready, and the Js side starts loading main.bundle. Js, which contains all the Js and React logic and components.

  4. The Js side sends a JSON message to the Native side through the Bridge, telling the Native side how to create the UI. It is worth noting that all communication over the Bridge is asynchronous and sent as a package. This is to avoid blocking the UI, for example:

  1. The Shadow thread gets the message first and creates the UI tree

  2. It then uses the Yoga layout engine to get all flex style layouts and convert them into Native layouts, width, height, spacing, etc.

  3. UIManager then does something and displays the UI on the screen like this:

These are the main steps to launch your App.

RN has the following advantages based on this architecture:

  • The UI is not blocked: the user feels more fluid
  • No need to write Native code: with RN libraries, a lot of code can be written in JavaScript only
  • Performance is much closer to Native
  • The whole process is complete. Developers don’t have to control it and fully understand it

However, there must be disadvantages as well as advantages. Let’s take a look at a new architecture that addresses the existing shortcomings: Fabric.

Part 3: The pros and cons of Bridge and Fabric architecture

Now that we’ve discussed RN’s current architecture, it’s time to talk about the pitfalls. Take a look at what Facebook’s React team lead wrote on her blog.

The disadvantages of the current architecture are:

  • There are two different domains: JS and Native, which are not really aware of each other and do not share the same memory.
  • The communication between them is asynchronous communication based on Bridge. But it also means that there is no guarantee that the data will get to the other side in time.
  • Transferring big data is very slow because memory cannot be shared and all data transferred between JS and native is a new copy.
  • The UI could not be updated synchronously. Let’s say I have a FlatList, which loads a lot of data when I swipe. In some boundary scenarios, when there is user interface interaction, but the data has not been returned, the screen may flicker.
  • The RN repository is too large. As a result, libraries are heavier and the open source community is slower to contribute code or release fixes.

But don’t get me wrong: Facebook itself is developing apps using React Native to serve millions of daily users. There are other well-known companies that use RN based on the current architecture in their production environments, such as Wix, Bloomberg, Tesla, Zynga, and more.

The RN development team is working to address the shortcomings mentioned above.

Here is the previous RN schema:

Here is the new architecture diagram:

Let’s explain these new concepts: JSI, Fabric, Turbo Modules, and CodeGen.

  1. JSI(will replace Bridge) – in order for JS and Native to be aware of each other. Serialized JSON will no longer need to be transferred over the Bridge. Will allow Native objects to be exported as Js objects and vice versa. Both sides also export apis that can be called synchronously. In fact, the rest of the architecture is based on this (Fabric, Turbo Modules, etc., explained below)

  2. Fabric — the new name for UIManager, will be responsible for Native rendering. Unlike the current Bridge, it can export its Native functions via JSI, which can be referenced directly in the JS layer, and in turn, the Native layer can call the JS layer directly. This results in better and more efficient performance and data transfer.

  3. Turbo Modules. Remember the Native component above? Text, Image, View, their new name is Turbo Modules. The functions of components are the same, but the implementation and behavior may differ. First, they load lazily (they only load when the App needs them), and now they all load at startup. In addition, they are also exported via JSI, so JS can take references to these components and use them in React Natvie JS. In particular, this will lead to better performance at startup.

  4. CodeGen – To make the JS side the only trusted source for communication between the two ends. It allows developers to create STATIC JS classes so that the Native side (Fabric and Turbo Modules) can recognize them, and avoids the need to validate data every time => which would lead to better performance and reduce the likelihood of data transmission errors.

  5. Lean Core — Changes to the React Native library architecture. The goal is to lighten the load on the lib and help the community resolve more pull requests faster. Facebook is in the process of splitting out parts of the library, and you can see what they’re doing on Github. Like this one:

By the way, here’s an example you can try out in Chrome, which is a source of inspiration for how JSI works and exports objects:

Open the developer interface in Chrome, type console.log, and press Enter. You will see native code. This shows that console.log is a Native function.

Let’s take a look at how the App startup process looks with the new architecture.

  1. The user clicks on the App icon

  2. Fabric loads Native side (no Native component)

  3. Then notify the JS thread that the Native side is ready, and the JS side loads all main.bundle. JS, which contains all the JS and react logic + components

  4. JS is called to the Fabric via a reference to a Native function (exported by the JSI API), while the Shadow Node creates the same UI tree as before.

  5. Yogo performs layout calculations, converting flexbox-based layouts into terminal layouts.

  6. Fabric performs operations and displays UI==>

To complete the process, we did almost the same thing, but without the Bridge, now we can have better performance, we can operate synchronously, and we can even prioritize synchronized operations on the UI. Startup times will also be faster and apps will be smaller.

So, when are we going to be able to use these things?

You can follow their respective updates on Github:

  1. JSI
  2. Fabric
  3. Turbo Modules
  4. Lean Core
  5. CodeGen

In theory, most of the changes will be completed gradually and hopefully released in the fourth quarter of 2019 or the first quarter of 2020.

Partial reference documentation for a deeper understanding:

  • Latest RN news from Core Team- facebook.github. IO /react-nativ…
  • Parashuram post about the new architecture blog.nparashuram.com/2019/01/rea…
  • Pharam New 2019 Lecture React Amsterdam — www.youtube.com/watch?v=NCL…
  • Levelup.gitconnected.com/wait-what-h…
  • Layout engine explnation – www.freecodecamp.org/news/how-re…
  • Four Parts Article About the New Architecture by Lorenzo from Formidable (Part 1 Here Links to the Others) — Formidable.com/blog/2019/r…
  • FB State of React Q4 2018 by Sophie Alpert from FB team at this time — Facebook.github. IO/React – Nativ…