I. Introduction
On July 14, Joshua Gross of the React Native core team said on Twitter that RN's new architecture has been implemented within Facebook, and 99% of the code has been open source. In fact, as early as June 2018, Facebook officially announced a large-scale refactoring of React Native plans and refactoring roadmap, the purpose is to make React Native more lightweight, more adaptable to hybrid development, close to or even achieve the original experience.
This architecture upgrade is of great significance to React Native. According to the official statement, the performance of the upgraded RN will be greatly improved, mainly to solve the performance problem that has been criticized for a long time. The following figure is a release note of React Native.
In order to make RN more lightweight, more adaptable to hybrid development, and close to or even achieve a native experience, React Native's optimization measures include the following aspects:
- Change the threading model, UI updates no longer need to be triggered on three different threads at the same time, but can call JavaScript synchronously on any thread for priority updates, and at the same time push low-priority work out of the main thread to keep the UI responsive .
- The introduction of asynchronous rendering capabilities allows multiple renderings and simplifies asynchronous data processing.
- Simplified the rendering logic of JSBridge and optimized the underlying rendering architecture to make it faster and lighter.
Second, the new and old architecture comparison
Those who have experience in RN development know that the communication between the JS layer of the original RN architecture and Native relies too much on Bridge, and it is asynchronous communication, which makes it difficult to achieve some interactions and designs with high communication frequency. Affect the rendering of the page. The new architecture also starts from this point. A lot of changes have been made to the Bridge layer, so that the UI and API calls can be adjusted from the original asynchronous method to synchronous or asynchronous communication with Native, which solves the bottleneck problem of frequent communication. .
At the same time, the new architecture uses JSI (the full name is JavaScript Interface) instead of the original Bridge, and the JS layer directly calls the C++ layer and then calls Java/OC to realize the mutual operation between JS and Java/OC, greatly improving the efficiency of communication. Thanks to the new architecture of JSI, JavaScript can directly call the methods of the Native module.
Third, the old architecture
Before introducing the new architecture, let's take a look at the current architecture of the RN framework, one of its shortcomings, and why Facebook wants to refactor the entire framework. Currently, the architecture used by RN mainly includes three parts: Native, JavaScript, and Bridge. Native manages UI updates and interactions, JavaScript calls Native capabilities to implement business functions, and Bridge transmits messages between the two. The entire architecture is as shown in the figure below.
As you can see, the architecture of React Native is still very clear. The top layer provides React-like support and runs in the JavaScript runtime environment provided by JavaScriptCore. The Bridge layer connects JavaScript with the Native world. Then, Bridge is divided into three parts, in which Shadow Tree is used to define UI effects and interactive functions, Native Modules provide Native functions (such as photo albums, Bluetooth), and their mutual communication uses JSON asynchronous messages.
3.1 Bridge
In the current architecture, the Bridge layer is the key to React Native technology. It has the following characteristics:
- Asynchronous (asynchronous): Does not rely on synchronous communication.
- Serializable: Ensure that all UI operations can be serialized into JSON and converted back.
- Batch processing (batched): Queue Native calls and process them in batches.
3.2 Thread model
In the old architecture, React Native has a total of 3 threads, namely UI Thread, Shadow Thread and JS Thread.
- UI Thread: The main thread in an Android/iOS (or other platform) application.
- Shadow Thread: The thread that performs layout calculation and constructs the UI interface.
- JS Thread: JavaScript code such as React is executed on this thread.
The relationship before them is as follows:
3.3 Startup process
For RN applications, after the App is started, the React Native runtime environment (ie Bridge) needs to be initialized. After the Bridge is ready, the JS code can be run, and then Native rendering can be executed. The complete startup process is as follows:
Among them, the initialization of Bridge involves the following process:
As you can see, the initialization of Bridge is mainly divided into 4 steps:
- Load JavaScript code: download from the network in development mode, read from device storage in production environment
- Initialize Native Modules: load and instantiate all Native Modules according to the registration information of Native Module
- Inject the Native Module information: take the Native Module registration information and inject it into the JS Context as a global variable
- Initialize the JavaScript engine: JavaScriptCore
3.4 Rendering process
As mentioned earlier, React Native has a total of 3 threads, namely UI Thread, Shadow Thread and JS Thread.
In the rendering process, the JS thread passes the view information (structure, style, attributes, etc.) to the Shadow thread to create a Shadow Tree for layout calculations. After the Shadow thread calculates the layout, it then transfers the complete view information (including width and height). , Location, etc.) are passed to the main thread, and the main thread creates the view accordingly.
For events that need to be responded to, the main thread packs the relevant information into event messages and passes them to the Shadow thread, then generates the specified event of the corresponding element according to the mapping relationship established by the Shadow Tree, and finally passes the event to the JS thread to execute the corresponding JS callback function.
The complete rendering process is as follows:
Through the above analysis, it is not difficult to find that the current architecture is strongly dependent on nativemodule, which is commonly referred to as bridge. For simple Native API calls, the performance is acceptable, but for UI, every operation is required. Through bridge, including height calculation, update, etc., and bridge limits the frequency of calling and only allows asynchronous operations, it is difficult for some front-end updates to be reflected on the UI in time, especially operations that are similar to sliding, animation, and update frequency. , So you can often see a blank screen or freeze.
Fourth, the new architecture
In the current architecture, the communication between the JS layer and the Native is too dependent on Bridge, which makes it difficult to implement some interactions and designs with high communication frequency, and also affects the rendering performance. Based on the above problems, in the new design, React Native proposed several new concepts and designs: JSI, Fabric and TuborModule.
- JSI (JavaScript interface): The core focus of this restructuring is also because of JSI. The original heavily dependent Native Bridge architecture is decoupled, and the communication cost between the JS layer and Native is greatly reduced.
- Fabric: Relying on the design of JSI, moving the shadow tree layer under the old architecture to the C++ layer, so that one-to-one control of the front-end components to the UI components can be realized through JSI, which eliminates the asynchronous and batch operations of the UI under the old architecture. Cost of communication.
- TuborModule: The new native API architecture replaces the original Java module architecture. In addition to supporting basic types in the data structure, it also supports JSI objects, allowing the front-end and client-side APIs to form a one-to-one call.
The following is a schematic diagram of the new architecture of React Native:
It can be seen that in the new architecture scheme, the Bridge layer is replaced by the new JSI. Unlike the previous direct input of JavaScript code to JSC, the new architecture introduces a layer of JSI (JavaScript Interface). As an abstraction on top of JSC, JSI is used to shield the differences of JavaScript engines and allow different JavaScript engines (such as Hermes) to be used.
The new JSI layer contains two parts, Fabric and TurboModules. Among them, Fabric is responsible for managing the UI, and TurboModules is responsible for interacting with Native. Fabric implements the rendering layer of React Native in a more modern way, simplifying the complex cross-thread interaction process in the previous rendering process (React -> Native -> Shadow Tree -> Native UI). And TurboModules also supports loading Native modules on demand, thereby reducing the performance overhead caused by RN initializing Native modules.
4.1 JSI
As mentioned earlier, in order to upgrade the architecture of RN, RN proposed a new concept of JSI. With JSI, JavaScript can directly hold references to C++ objects and call its methods. JSI has been supported since 0.60. It is an adaptation architecture designed by Facebook on the JS engine. It allows developers to register the JavaScript interface of methods to the JavaScript runtime, and these registration methods can be written in C++. In addition, JSI also brings some of the following features:
- Standardized JS engine interface, React Native can replace engines such as v8 and Hermes.
- Optimize and upgrade the communication between JS and native java or Objc, but different from the way JSBridge uses memory sharing and proxy classes, in order to achieve direct communication with the Native side, JSI provides a layer of JSI::HostObject implemented in the C++ layer. This data The structure supports propName and also supports parameter transfer from JS.
- The original data communication between JS and Native used JSON and basic types of data, but with JSI, the data types are richer and support JSI Object.
Therefore, the API calling process under the new architecture: JS->JSI->C++->JNI->JAVA, each API is more independent, and it is no longer necessary to rely on Native modules. But this also brings another problem, that is, when designing an API, developers need to encapsulate a set of interfaces such as JS, C++, JNI, Java, etc., and the requirements for developers are still relatively high. However, fortunately, Facebook provides a codegen module that can help developers complete the basic code and environment construction.
Regarding the process of packaging jsi, please refer to develop JSI Module
4.2 Fabric
Fabric is the UI framework of RN's new architecture, which is similar to the original UImanager framework, but there is still a big gap between the rendering performance of UImanager and the rendering performance of native components and animations. To give a more common problem, there will be a long white screen time when the Flatlist is quickly swiping, and it is difficult to support interactive animations and gestures. Therefore, RN adopts a new Fabric framework.
Simply put, the JS layer newly designed FabricUIManager, the purpose is to support Fabric render to complete the rendering and update of components. Due to the JSI design, FabricUIManager can communicate directly with the cpp layer, corresponding to the C++ layer UIManagerBinding. In fact, each operation and API call has a corresponding creation of a different JSI. From here, all the original dependence on UIManager is completely removed. The problem of Native bridge, and the measure of component size has also got rid of the dependence on Java and bridge, and is directly completed in the shadow of the C++ layer to improve rendering efficiency.
With JSI, UI operations that previously relied on bridge in batches can be executed synchronously to the C++ layer. In the C++ layer, the new architecture has completed the construction of a shadow layer, while the old architecture is implemented in the java layer, so from this aspect In other words, the rendering performance has also been greatly improved.
4.3 TurboModule
In the previous architecture, Native Modules (whether they are needed or not) must be initialized when the application starts, because Native does not know which functional modules JavaScript will call. The new TurboModules allows native modules to be loaded on demand and directly hold their references after module initialization, instead of relying on message communication to call module functions. Therefore, the startup time of the application will also be improved. And, 0.64 version already supports the use of TurboModule.
In general, TurboModule is designed to facilitate JS methods that can be directly called to C++.
4.4 CodeGen
The new architecture UI adds the shadow and component layers of the C++ layer, and most of the components are based on JSI, so the process of developing UI components and APIs is more complicated. Developers are required to have C++ and JNI programming capabilities, in order to facilitate developers to quickly Development Facebook also provides a codegen tool to help generate some automated code.
CodeGen tool refers to . At the same time, because codegen has not yet been officially released, there is almost no documentation on how to use it, and it will not be known until it is open sourced.
In addition, JSI and Turbomodule are already available in the latest version, and the developer community has also used JSI to develop a large number of API components, such as:
- https://github.com/mrousavy/react-native-vision-camera
- https://github.com/mrousavy/react-native-mmkv
- https://github.com/mrousavy/react-native-multithreading
- https://github.com/software-mansion/react-native-reanimated
- https://github.com/BabylonJS/BabylonReactNative
- https://github.com/craftzdog/react-native-quick-base64
- https://github.com/craftzdog/react-native-quick-md5
Judging from the latest updates, RN’s new architecture seems to have entered a countdown before the release. As a loyal fan of RN, I have always hoped that RN can release version 1.0 as soon as possible.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。