Rishabh Pancholi
Mindful Engineering
5 min readMar 22, 2022

--

Fabric Architecture-React Native
By MindInventory

In recent times, React-Native has become one of the trending platforms for developing mobile applications. However, these made me curious to know about the architecture that React-Native uses. Currently, Fabrics architecture is the latest rendering system that has been used by react-native.

What Is Fabric?

Fabric aims to rebuild the rendering layer of react-native. In the current interoperability, all the UI operations are handled by a sequence of cross-bridge steps. However, the new implementation allows for the UI manager to create the shadow tree directly in C++, which greatly increases the swiftness of the process by reducing the number of jumps across realms. Basically, this greatly improves the responsiveness of the User Interface. In other words, it is a render optimization for screens, basically, it improves performance dramatically.

Also, by using the JSI, Fabric exposes the UI operations to JavaScript as functions: the new Shadow Tree (which determines what to really show on screen) is shared between the two realms, allowing straight interaction from both ends.

And, if that wasn’t already a great improvement, this direct control from the JavaScript side allows having the priority queues from the new React for the UI operations, in order to have opt-in synchronous executions where it benefits performance. This foundation will allow for improvements in common pitfalls like lists, navigation, and gesture handling.

Current Architecture Structure

by Lorenzo Sciandra

There were four core sections in the old architecture: the React code written by the developer (which is very similar to its web counterpart), the JavaScript that gets interpreted from what you write, a series of elements collectively known as “The Bridge,” and the Native side.

The key aspect of the current architecture is that the two realms, JavaScript and Native, are not really “aware” of each other. This means that to communicate, they rely on asynchronous JSON messages transmitted across The Bridge. These are sent to the native code with the expectation (but not a guarantee) that they will elicit(manage to get) a response sometime in the future.

New Architecture Structure

by Chen Feldman
  1. JSI:- It will replace the bridge from the current architecture. Actually, JSI provides API to the JS Runtime engine(where js code is executed when you run it) and makes JS aware of the native functions and objects directly, without any bridge. It benefits us by synchronizing calls from JS thread to Native and vice-versa. Renders fast using a direct call to UI Main Thread and also sharing data between threads.
  2. Fabric:- the new name for the UIManager which will be responsible for the native side. The biggest difference now is that instead of communicating the JS side by the bridge, it will expose its native function using the JSI so the JS side and vice-versa can communicate directly through ref functions. Better and efficient performance and passing data between sides.
  3. Turbo Modules:- The purpose of Turbo modules is the same as native modules in the current architecture but are implemented and act differently. At first, they are lazy-loaded which means it only loads when the app needs them instead of loading all of them on the launch time. In addition, they are also exposed using the JSI so JS holds a ref to use them on the React Native JS lib side which results in better performance, especially on the launch time.
  4. CodeGen:- It is used to make JS a single source of truth which will help us to create static types of the js so the native side(fabric and turbo modules) will be aware of them and will avoid validating the data each time which results into minimal time consumption, better performance and fewer chances of mistakes while passing data.

The flow of new architecture:

  1. The user clicks on the app icon.
  2. Fabric directly loads the native side (no native modules).
  3. It tells the JS thread that it is ready and now the JS side loads all the main.bundle.js which contains all js and react logic + components.
  4. JS called through the ref native function (the one that was exposed as an object using the JSI API) to Fabric and the shadow node creates the tree as before.
  5. Yoga does the layout calculation converting from flexbox-based style to host layout.
  6. Fabric does its thing and shows the UI.

Where It Is Used?

react-native-screens with Fabric:

There has been an implementation done in react-native-screens with both new and old architecture. To Make your first fabric app with react-native-screens you need to follow the following steps:

  1. Create a new app using React Native CLI: npx react-native init NewRN68App --version 0.68.0-rc.1
  2. Add react-native-screens the same way as usual: yarn add react-native-screens
  3. Now, to enable Fabric on iOS, you need to run RCT_NEW_ARCH_ENABLED=1 pod install in the ios folder.
  4. For Android, you need to change newArchEnabled=true in android/gradle.properties
  5. Now you can proceed to build the app as usual on both Android and iOS. The installed version of screens will automatically detect whether Fabric is enabled and will serve an appropriate implementation.

An overview of the migration process

All the communication that has been done between native and JS components is done via JSI (a C++ API to communicate with Objective C code on iOS and Java code on Android). The information from one side to another is moved using C++ functions instead of being serialized/deserialized(convert an object into a string or vice-versa) in order to be passed over the bridge. Because of that, libraries that intend to support the new architecture need to adapt to this new interface. Using JSI is relatively straightforward if you are building a completely new library while implementing it in the existing library might be challenging. Here, we want to be able to support both fabric and existing versions with a minimum amount of shared code between these two implementations as possible.

The main steps behind the migration process for an existing library are mentioned below:

  • Write components specifications in Flow by doing a dialect(a variant of language) of JS. This code will be the root of the application. It gives us the specification used on both the native and JS side. The code is also used to engender native implementation for ensuring the type safety.
  • In the next step, we added implementations on the native side that can handle props and events. On Android, the codebase is shared between old and new architecture. On iOS, new files are created to make both the implementations independent.
  • To keep the working of both the architecture in the library, we have a number of files/classes that are specific to a given architecture.

Conclusion

To sum up, the launch of the new architecture will surely take React-Native ahead. The user experience will definitely become smoother and the release of a fabric-compatible version of react-native-screens is a breakthrough to adapt the new React-Native architecture. I hope this article helped you to know about the huge changes that the community brought in their architecture.

--

--