React Native New Architecture

Abhishek Mishra
9 min readJun 12, 2023

--

What is React Native

React native is a framework that helps to create cross-platform native mobile applications (for iOS and Android) with the help of JavaScript and TypeScript. React Native was developed by FaceBook.

Single code base works for both platforms and it saves a lot of money and time for mobile apps.

React Native uses Android and iOS elements to compile Native apps for both platforms. It makes maintaining a code base easier.

Prerequisite

· Should know about React Native to understand this, basic knowledge of react native is mandatory.

What is Old Architecture and how it works?

React native current architecture has 3 things to understand.

JavaScript Thread JavaScript code bundle runs in this thread with help of JavaScript engine (JSC, Hermes etc.)

Native Thread Native UI rendering and handling user events (click, swipe etc.) runs in native thread.

Bridge these 2 threads run separately in 2 different worlds and don’t know each other’s technology. To make the whole system work there must be some mechanism to talk to each other. The mechanism that helps to communicate these 2 separate threads is called Bridge.

How Native and JavaScript Threads communicate in Old Architecture?

To communicate between these two completely different threads there must be some common language that language will be JSON. To send information to each other, Thread sends messages in asynchronous manner.

From JavaScript to Native

For example, the react native side sends information in JSON format to the native side for rendering screen on the native side. This JSON data waits in queue to be processed by Native UI thread, when Native UI thread gets free, it processes that JSON information and renders the screen accordingly.

From Native to JavaScript

In the same way native side sends information of user events to the JavaScript side. JSON data waits in queue to be processed by JavaScript thread, when JavaScript thread gets free, it runs the code with help of JavaScript Engine and sends updated screen in JSON format to the native side.

Role of Bridge

Bridge behaves like a broker to communicate between these two different threads that do not understand each other technically but they understand how to consume JSON and act accordingly. The Bridge can be imagined as a bus where the producer layer sends some data for the consumer layer. The consumer could read the data, deserialize it and execute the required operations..

What is the benefit of Old Architecture?

Since it is asynchronous communication so it’s non-blocking communication. it helps in smooth view management on screen at 60fps.

What are the limitations of Old Architecture?

This architecture has some limitations:

It is asynchronous: one side submitted the data to the bridge and asynchronously “waited” for the other side to process that.

It is single-threaded: JavaScript side work on a single thread; therefore, the computation that happened in that world had to be performed on that single thread.

It imposed extra overheads: every time one side had to use the other side, it had to serialize data information. The other side had to deserialize data. The chosen format was JSON for its simplicity and human-readability, but despite being lightweight, it has a cost to pay.

JSC bundled with Android APK: since the “JavaScriptCore” engine is only present on iOS devices. The JSC engine needs to be part of the Android APK bundle.

Bridge is Bottleneck: bridge is bottleneck for fast communication.

Native modules need to load on start: since both sides do not know each other and their object types. It creates a new type of problem that JavaScript cannot start modules when needed, applications have to load all native modules on the start of the application.

Why New Architecture?

Meta team also understands/knows this limitations/bottleneck/problem of bridge architecture, so they started working to eliminate these bottleneck/problems with below mentioned benefits.

Synchronous execution no more async message transfer between JavaScript and Native thread.

No more overhead to serialize and decentralize JSON data while transferring data between JavaScript and Native thread.

Faster Startup time.

Better memory management.

Less crashes.

Better code quality (Type Safe).

What is New Architecture?

From React Native version 0.68.0, React Native provides New Architecture. New Architecture helps developers for performance, better memory management, and lesser TTI (time to interaction) of the applications.

The core concept of React Native still holds true with New Architecture.

● React Native uses the Native components to create reusable UI components on the screen to achieve native UI experience.

● React Native uses the native modules to access platform specific API/hardware.

New Architecture have 4 main things to understand.

JavaScript Interface (JSI) this will replace bridge and make possible communication between JavaScript and Native thread.

Fabric is React Native’s new rendering engine, an evolution of the legacy renderer.

Turbo Modules next upgraded version of Native Modules with few extra benefits.

CodeGen is a tool that helps in type safety between both worlds.

JavaScript Interface (JSI)

The key feature of New Architecture is JSI. JSI just enables the interface/awareness between JavaScript layer and the native layer. This JSI is written in C++, that’s why it’s not limited to just Android or iOS, it also can integrate with anything written in C++.

JSI holds the reference object (stores a C++ pointer) of elements. These objects have shared ownership of both layers, so that JavaScript layer directly invokes methods of Native elements and Native layer can send events to JavaScript layer. This reference object helps in synchronous communication between JavaScript and Native thread. Whenever the React Native layer wants to update the UI screen, React Native send message synchronously to the Native side and Native layer acts accordingly.

Turbo Modules

This JSI revolutionized the communication between JavaScript and Native layers. Due to this direct communication between both layers, JavaScript can directly send messages to Native layer with high priority and JavaScript can load native modules whenever it is needed.

For example, in the old architecture Application must load all the native modules on the start of the application. If the application needs to access the camera, then the camera native module must be loaded on the start of the application whether this camera is opened by application or not.

In the new architecture, if an application needs a camera module on the 4th screen of the application, then the application can load the camera module when ever it required. This on demand load of native modules helps a lot in the TTI (Time to Interaction) of the application.

Fabric

Fabric is the evolution of existing rendering system. The core principles are to unify more render logic in C++, improve interoperability with the host (iOS, Android) platform, and to unlock new capabilities for React Native.

The React Native renderer goes through a sequence of work to render React logic to a host (iOS, Android) platform. This sequence of work is called the render pipeline and occurs for initial renders and updates to the UI state.

The render pipeline can be broken into three general phases:

1. Render

2. Commit

3. Mount

Render: React executes code logic which creates React Element Trees in JavaScript. From this React Element Trees tree, the renderer creates a React Shadow Tree in C++.

Whenever React creates a parent-child relationship between two React Element Nodes of React Element Trees, the renderer creates the same relationship between the corresponding React Shadow Nodes of React Shadow Trees. This is how the React Shadow Tree is assembled.

The operations (creation of React Shadow Node, creation of parent-child relationship between two React Shadow Nodes) are synchronous and thread-safe operations that are executed from React (JavaScript) into the renderer (C++), usually on the JavaScript thread.

The React Element Tree does not exist indefinitely in memory, it is a temporal representation materialized by “fibers” in React. Each “fiber” (In order to do any work, first need a way to break work down into units, a fiber represents a unit of work) that represents a Host View Tree Node (host component) stores a C++ pointer to the React Shadow Node, made possible by JSI.

The React Shadow Tree is immutable. To update any React Shadow Node, the renderer creates a new React Shadow Tree. However, the renderer provides cloning operations to make state updates more performant.

After the React Shadow Tree is complete, the renderer triggers a commit of the React Element Tree.

Commit: After a React Shadow Tree is fully created, the renderer triggers a commit. This promotes both the React Element Tree and the newly created React Shadow Tree as the “next tree” to be mounted. This also schedules calculation (with help of Yoga layout manager) of its layout information.

Commit phase has two tasks to complete.

Layout Calculation: task calculates the size and position of each React Shadow Tree node by invoking layout manager Yoga to calculate the layout of each React Shadow Tree node. This calculation requires.

1. Style of React Shadow Tree node which originated from React Element Tree node.

2. And the style constraint of the root React Shadow Tree, to calculate available space for newly generated nodes.

Tree Promotion: task promotes newly created React Shadow Tree as “Next Tree”. This promotion task indicates that the newly created React Shadow Tree has all the information to be mounted on the screen and represents the latest state of the React Element Tree.

Mount: The React Shadow Tree, now with the results of layout calculation, is transformed into a Host View Tree.

This phase transforms React Shadow Tree into the “Host (iOS, Android) View”. Render creates corresponding “Host (iOS, Android) View” for each React Shadow Tree node and mounts it on the screen.

Mound phase has 3 tasks to complete.

Tree Diffing: Step computes the difference between previously Rendered Tree and newly created “Next Tree” in C++. This step involves flattening the React Shadow tree to avoid unnecessary “Host (iOS, Android) View” nodes.

Tree Promotion: task promotes Next Tree to “Rendered Tree”.

View Mounting: task do atomic mutation operations onto corresponding host views. This step executes in the host platform on UI thread.

CodeGen

So, C++ is a strongly typed language and JavaScript/TypeScript is not a strongly typed language. To communicate between both the JavaScript and C++ there must be some interface. “CodeGen” is a tool that helps to create the interface from the JavaScript/TypeScript that generated interfaces helps to communicate between both C++ world and JavaScript world.

The “CodeGen” is not a proper pillar, but it is a tool that can be used to avoid writing a lot of repetitive code. Using “CodeGen” is not mandatory: all the code that is generated by it can also be written manually. However, it generates scaffolding code that could save you a lot of time. The “CodeGen” is invoked automatically by React Native every time an iOS or Android app is built.

Final understanding of New Architecture

What are the Benefits of New Architecture?

New Architecture has various benefits.

Synchronous execution: it is now possible to execute synchronously those functions that should not have been asynchronous in the first place.

Concurrency: it is possible from JavaScript to invoke functions that are executed on different threads.

Lower overhead: the New Architecture doesn’t have to serialize/deserialize the data anymore; therefore, there are no serialization taxes to pay.

Code sharing: by introducing C++, it is now possible to abstract all the platform agnostic code and to share it with ease between the platforms.

Type safety: to make sure that JS can properly invoke methods on C++ objects and vice-versa, a layer of code automatically generated has been added. The code is generated starting from some JS specification that must be typed through Flow or TypeScript.

--

--