Exploring React Native’s Architectures: Bridge and Beyond

Antônio Gally
6 min readNov 27, 2023

--

By Antonio Gally, a cool Software developer

https://uds.com.br/blog/react-native-o-que-e/

When it comes to the architecture of any technology, things usually get a bit more complicated, but it’s always worth exploring. In this post, we’re going to take a deep dive into the two architectures of React Native, exploring technical diagrams and schemes in detail. This is an advanced post about React Native, aimed at those who already have some familiarity with the framework.

If you’re just beginning to understand how React Native works, this post might not be the best starting point (yet). So, for those ready to delve into the complexities of React Native architectures, let’s get started on this technical journey!

Why two architectures?

React Native was initially built on the Bridge architecture, which faced performance issues. In response, Facebook started developing a new architecture called Fabric in 2018, aiming to replace Bridge. Fabric began its rollout in 2021, first being used in Facebook’s internal apps. However, according to the official React Native documentation, Fabric is still in the rollout phase and not yet fully deployed in production. As of now, new React Native apps still predominantly use the Bridge architecture.

Bridge

In this diagram, we can see three principal threads that exists when we run our app using Bridge’s architecture. Let’s talk about the responsability of each of them:

  • Js Thread will run all our React code
  • Shadow Thread will create native styles and positions from our components
  • Main Thread will draw our UI and listen to events

JS Thread

The JS Thread runs our React code, bundled by Metro Bundler and interpreted by either the JSC or Hermes JavaScript engine.

All of our React code runs in the JS (JavaScript) Thread, undergoing a bundling process with Metro Bundler. This process generates a JS Bundle, which is then ready to be interpreted by a JavaScript Engine. This engine can be the browser’s default JavaScriptCore (JSC) or Hermes, an enhanced engine specifically created for React Native by Facebook’s team.

Shadow Thread

The Shadow thread in React Native transforms our flexbox layout into a format understood by native platforms (Android/iOS) using the Yoga layout engine.

Although we write our layout in flexbox style, the host platforms (Android/iOS) have their own distinct layout systems and don’t inherently follow flexbox rules. To bridge this gap, React Native employs the Shadow thread. This thread processes the layout dimensions and positions from our flexbox code, creating a layout tree (React Shadow Tree) that corresponds to the native system’s requirements. At its core, the Shadow thread utilizes Yoga, a layout engine that effectively translates our flexbox-based layout into a format compatible with the native operating systems.

Main Thread

It converts layout instructions into visual components, handles user interactions and events for responsiveness, and manages Native Modules for integrating native platform features.

The Main Thread plays a crucial role in React Native’s architecture. Its primary responsibility is to render the Shadow Tree, an operation that forms the basis of what is referred to as the ‘Host View Tree’ in the Fabric architecture. Essentially, this thread takes the layout calculations and instructions prepared by the Shadow thread and turns them into actual visual components on the screen.

Beyond UI rendering, the Main Thread handles user interactions and events, like taps and swipes, ensuring responsive and interactive user experiences.

Additionally, the Main Thread manages Native Modules. These modules enable access to native platform features, such as the device’s camera or push notifications, and are essential for integrating platform-specific functionalities not directly available in JavaScript.

After discussing those three threads in the Bridge architecture, let’s now explore the Bridge itself. How exactly does JavaScript communicate with native code, and vice versa?

The Bridge in React Native is a message queue system that utilizes JSON messages for communication between JavaScript and native platforms.

The Bridge is a fundamental architecture in React Native, enabling the communication between JavaScript code and the native components of a mobile application. It operates asynchronously, utilizing JSON objects for a bidirectional exchange of information between JavaScript and the native environment. Key characteristics of the Bridge include:

  • Batched Bridge: Rather than sending operations individually, React Native batches them together before sending them over the Bridge. This approach significantly optimizes performance by reducing the communication overhead.
  • Serializability: All data transmitted across the Bridge must be serialized. This means complex JavaScript objects are converted into strings, sent across the Bridge, and then deserialized or parsed on the receiving side.
  • Asynchronous Nature: The Bridge’s operations are inherently asynchronous, meaning they don’t occur instantaneously. This characteristic ensures that the JavaScript thread remains unblocked, allowing the UI and other processes to run smoothly without waiting for the Bridge operations to complete.
Event flow on Bridge’s architecture

The Bridge’s problem

Understanding that every interaction in React Native, from events to screen updates, requires data to be serialized, passed through the Bridge, and then deserialized — in an asynchronous manner — leads us to the crux of the issue: performance. Consider a scenario where your app needs to display a large amount of data, constantly updating in response to numerous events. In this situation, the Bridge becomes a bottleneck. The process of serializing, transmitting, and then deserializing vast amounts of data can lead to noticeable delays. The result? Your screen might temporarily go blank during heavy data updates, a clear indicator of performance strain in the Bridge architecture.

In a talk by Parashuram, an engineer on the React Native team, he provides a practical example of the performance challenges associated with the Bridge architecture. In his presentation, he discusses various aspects of React Native, with a particular focus on handling data asynchronously. Parashuram emphasizes an important point:

‘Not everything needs to be asynchronous!’

He explains that in an asynchronous environment, like that of React Native’s Bridge, native events, once initiated, cannot be canceled. This limitation means there’s an inherent delay in responsiveness. Consequently, the more data or events being processed asynchronously, the slower the response time becomes, impacting the app’s overall performance.

Given these challenges, the team at Facebook embarked on developing an entirely new architecture named Fabric, aimed at overcoming the limitations of the traditional Bridge. I’ll be dedicating an upcoming post exclusively to exploring Fabric and its advancements.

If you’ve read this far, thank you for your interest and engagement! I’d love to hear your thoughts, so please feel free to leave a comment and share this article with others. Your support and feedback are greatly appreciated! Thanks a lot! ❤

Reference Links

--

--