This paper mainly introduces the new architecture of ReactNative(RN) that FB team is reconstructing, the main current architecture, problems caused by Bridge, new architecture, CONCEPTS such as JSI, Fabric, TurboModules, CodenGen and LeanCore.

The current architecture

RN now has three main threads

  1. JS thread. JS code execution thread, responsible for logical level of processing. Metro packages the React source code into a single JS file (the JSBundle shown here). Then pass to JS engine to execute, now ios and Android unified use JSC.
  2. UI Thread(Main Thread/Native Thread). This thread is responsible for Native UI rendering and calling Native Modules such as Bluetooth.
  3. Shadow of the Thread. This thread creates a Shadow Tree to simulate the React Tree. Shadow Tree can be similar to the virtual DOM. RN uses Flexbox layout, but native is not supported, so Yoga is used to convert Flexbox layout to native platform layout.

The problem of Bridge,

Start with a review of the current Bridge operation.

When we write the React source code like the following.

<View style={{
        backgroundColor: 'pink',
        width: 200, 
        height: 200}}/> 
Copy the code

The JS thread serializes it first, forming the following message

UIManager.createView([343,"RCTView",31,{"backgroundColor":-16181,"width":200,"height":200}])
Copy the code

To ShadowThread via Bridge. Shadow Tread receives this message, deserializes it to form a Shadow tree, and then passes it to Yoga to form the native layout information.

This is then passed to the UI Thread via the Bridge.

Once the UI Thread gets the message, it also deserializes it and draws it based on the given layout information.

As you can see from the above procedure, all three threads interact through the Bridge, so the bottleneck is there.

Bridge has three characteristics:

  1. Asynchronous. These message queues are asynchronous and cannot be guaranteed to handle events.
  2. Serialization. Delivering a message in JSON format is expensive as it goes through serialization and deserialization each time.
  3. Batch processing. Queue Native calls and process them in batches.

The benefit of asynchronous design is that it does not block. This design performs well in most cases, but can be problematic in some cases, such as waterfall flow rolling.

When the waterfall flows down, a request is sent to the server to get the data for the next rendering.

The scrolling event occurs on the UI thread and is then sent to the JS thread via the Bridge. The JS thread listens to the message and sends the request. The server returns the data and then returns it to Native for rendering through the Bridge. Since both are asynchronous, there are blank modules, leading to performance problems.

As can be seen from the above, the performance bottleneck is mainly the interaction between JS threads and Native. If there is no interaction, RN has a good performance.

Therefore, the optimization of RN, mainly focused on Bridge, has the following three principles:

  1. JS does not communicate with Native. The most thorough way, the message does not go through the Bridge.
  2. JS and Native reduce communication. At both ends of the unavoidable situation, try to reduce the frequency of communication. For example, multiple requests are merged into one.
  3. Less JSON size. For example, if the image is converted to Base64, the transmitted data will become larger and be replaced by network images.

RN can monitor Bridge communication through MessageQueue, the main code is as follows

import MessageQueue from 'react-native/Libraries/BatchedBridge/MessageQueue.js';

const spyFunction = (msg) => {
  console.log(msg);
};

MessageQueue.spy(spyFunction);
Copy the code

Here’s what we heard

The new architecture

The FB team became aware of these issues and was pressured by Flutter to come up with a new architecture in 2018

It is mainly composed of JSI, Fabric, TurboModules, CodeGen and LeanCode.

JSI

JSI is the core and cornerstone of the architecture, and everything is built on top of it.

JSI is short for Javascript Interface, a lightweight framework written in C++ that allows Javascript Objects to get reference to C++ Host Objects and call corresponding methods via JSI.

JSI has nothing to do with React and can be used with any JS engine (V8,Hermes).

With JSI, JS and Native can communicate directly. The call process is as follows:

JS->JSI->C++->ObjectC/Java

Since then, three threads do not need to communicate through Bridge any more, and can directly know the existence of each other, making synchronous communication become a reality. See the official example for specific usage.

Another benefit is that with JSI, JS engines are no longer limited to JSC and can be freely replaced with V8 and Hermes, further improving the speed of JS parsing.

Fabric

Fabric is a new UI layer in the entire architecture, including renderer and Shadow Thread in the new architecture diagram.

Below is the old communication model.

Three threads communicate asynchronously through the Bridge, and multiple copies of data are required.

With JSI, JS can directly call other threads to achieve synchronous communication mechanism. In addition, the data can be directly referenced without copying, thus becoming the following new communication mode.

In addition to the synchronization capability and direct references, another benefit of Fabric is that it now supports render priorities such as React’s Concurrent and Suspense modes

The following two images show the changes from startup to rendering, before and after the addition of Fabric.

After the transformation to Fabric

TurboModules

TurboModules are mainly related to Native application ability, corresponding to Native Modules on the new architecture diagram. The optimization of this part is as follows:

  1. Through JSI, JS can directly call Native modules to achieve some synchronous operations. Like calling the camera capability.
  2. Lazy loading of Native modules. Before, all Native modules would be loaded when RN framework was started, resulting in slow startup and long time. Now with TurboModules, load on demand, reducing startup time and improving performance.

CodeGen

CodeGen automatically translates statically typed JS code such as Flow or Ts into native code used by Fabric and TurboModules.

Lean Core

This part is mainly about slimming down packages. Previously, all packages were housed in RN core projects. The RN core now retains only the necessary packages, moving everything else to the React-native community or separating out separate components such as Webview and AsyncStore.

The current progress

  1. JSI has been released with RN0.59(jsiexecuter.cpp), but still uses Bridge to communicate
  2. Fabric and TurboModules are still in development and LeanCore has been completed
  3. You can now use C++ cross-platform modules.
  4. Backward compatibility is implemented for JS, not Native Modules.
  5. See the Fabric progress discussion and TurboModules Progress discussion, JSI progress discussion and CodeGen progress discussion, as well as the React official source code for details

RN’s new architecture is currently under intense refactoring, running a little behind schedule and looking forward to the release and performance of the new framework.

Netease Cloud music front-end development engineer recruitment

The job description

1. Responsible for or participate in front-end development of various types of projects (Web&Webview, RN, Hybrid Web, PC&MAC, small programs, creative activities, middle and background systems, etc.), and complete system design, technology selection and module development.

2. For the purpose of continuously improving quality, efficiency and experience, package components, deposit documents, production tools and build systems to enjoy the daily life of engineers

3. Share what I see and think in daily life, guide colleagues to grow together, and create a positive and healthy technical atmosphere.

Job requirements

1. Proficient in various Web front-end technologies and standards (Javascript, HTML, CSS), familiar with common page layout solutions, have a deep understanding of the separation of presentation and data, Web semantics, etc.

2. Master a data-driven view framework (React, Angular, Vue…) .

3. Familiar with common front-end construction tools (Webpack, etc.), and mature modular development thinking.

4. Familiar with common front-end data management solutions (such as Redux, Mobx, Rxjs, etc.), and know their advantages and disadvantages and application scenarios.

5, familiar with HTTP protocol, and master the relevant network debugging tools, have the background knowledge of server-side development.

6. Low tolerance for repetitive or non-standard work, able to solve the problem spontaneously through communication or technical means.

Bonus points:

1. A fundamental understanding of a larger front-end framework that goes beyond the documentation guidelines.

2. Solid Node foundation, practical experience in Node asynchronous programming and stability management, and experience in large-scale high-availability Node production environment implementation.

3. Rich experience in cross-end (PC & IOS & Android) development and practical experience in cross-end technology integration.

4. Experience in popular creative activities & games based on Web, with relevant framework or solution output.

5. Have the experience of working in a mature large front-end team of DACHeng, participate in the development or skilled application of internal precipitation infrastructure, and be able to know their improvement points.

6. Participated in high-quality open source projects as a leading or core contributor, and had in-depth thinking and insights on the operation of technical community.

contact

[email protected]

The resources

  1. react-native-fabric-why-am-i-so-excited
  2. React Native: See the Past, the Present and the Future
  3. How React Native constructs app layouts
  4. React Native EU 2019: Emily Janzer – The New React Native
  5. React Native — A Bridge To Project Fabric
  6. Chen Feldman – React Native – Under the Bridge