The paper

React Native’s main purpose is to enable developers to use the front-end React development framework to develop applications that run on multiple platforms. A simple understanding of front-end development allows us to quickly build a simple App. However, an in-depth understanding of the underlying principles of React Native can help us better locate problems encountered in development and solve problems from a multi-end perspective.

React works in the browser

Before we learn how React Native works, let’s review how React and the browser work: Babel compiles the React JSX syntax sugar into the React. CreateElement expression, which is the virtual DOM node, and then uses the Diff algorithm of the virtual DOM to compare the elements to be rendered by the browser’s rendering engine, thus forming a rich browser page. So how does React Native display React code on different platforms?

Architecture principles based on Bridge

The Bridge-based architecture used by React Native prior to version 0.59

  1. In the React Components development phase, Babel compiles code into browser-aware expressions and bundles them into jsbundles that are stored locally on the App device or on the server (hot update mechanism).
  2. After opening the App, load and parse the Jsbundle file and run it in JavascriptCore. The difference between Android and IOS is that IOS has a JavascriptCore native and Android needs to reload it. As a result, the initialization process on Android is slower than on IOS.
  3. The runtime needs to render the front-end components into the Native view. First, like the virtual DOM in React, a Shadow Tree will be constructed in the Bridge. Then, the Yoga layout engine will convert the Flex layout into the Native layout. Finally, UIManager was entrusted to complete the rendering of the components in the Native end.

The Bridge architecture is good for developers to shield the differences between platforms and provide a good near-native operating experience compared to WebView. However, the communication between Javascript and Native relies excessively on Bridge, which may cause a blank screen or event blocking when the interaction is frequent or the data is large. Moreover, serialization of JSON is inefficient. Under the pressure of a Flutter, no change means loss of users. How was React Native optimized after refactoring?

New architecture principles based on JSI

First, explain a few new concepts under the new architecture

  • JSI (Javascript Interface) : JSI allows Javascript to hold references to C++ objects and call their methods. At the same time, Native end (Android, IOS) supports C++. In this way, the serialization and deserialization of JSON using Bridge are avoided, and the direct communication between Javascript and Native end is realized.

JSI also blocks out differences between different browser engines and allows different browser engines to be used on the front end, so Facebook developed Hermes, an open source browser engine that is more suitable for Android, in response to Android’s need to load JavascriptCore.

  • CodeGen: As a tool to automate Javascript and Native compatibility, it allows developers to create STATIC JS classes so that Native (Fabric and Turbo Modules) can recognize them and avoid checking data every time, resulting in better performance. And reduce the possibility of data transmission errors.

  • Fabric: It is equivalent to the function of UIManager before, but the difference is that in the old architecture, the rendering at the Native end needs to complete a series of “bridge” operations, namely, React -> Native -> Shadow Tree -> Native UI. Under the new architecture, UIManager can create Shadow Tree directly through C++, which greatly improves the speed of user interface experience.

  • TurboModules: Due to the end-to-end separation between older architectures, even unused modules would be loaded and initialized at runtime. TurboModules shorten application startup times by allowing Javascript code to load corresponding Native modules only when needed and keeping direct references to them.

To sum up, Bridge in the old architecture was a performance bottleneck for interaction between React Native JS and Native JS, so the core change of the new architecture is to avoid serializing data from JavaScript to Native through Bridge.

conclusion

The content of the article refers to the articles of some big names at home and abroad, which may be difficult for beginners to understand. If you feel that it is not easy to understand, you can try to skip it first and come back to this part after the React Native combat, which may give you a deeper understanding.

The resources

  • React Native EU 2019: Emily Janzer – The New React Native
  • Part One: React and Codegen
  • Part Two: JSI and JSC
  • Part Three: Fabric and TurboModules
  • Part Four: The New React Native Architecture Explained
  • React Native architecture evolution