Skip to main content

Overlooking React Native from 1000km Altitude

Free2019-09-21#Tool#dive into React Native#React Native overview#React Native high level perspective#完全理解 React Native#鸟瞰 React Native

Examining React Native technology from three perspectives: history, architecture, and ecosystem

I. History: React Native from Beginning to Now

React Native's positioning is building native apps through React:

A framework for building native apps with React.

It has 5 major characteristics:

  • Create native apps for Android and iOS using React: Use React to create Android, iOS applications

  • Written in JavaScript—rendered with native code: What you write is JavaScript, what actually renders is Native interface

  • Native Development For Everyone: Develop based on platform-agnostic basic components to obtain platform native experience

  • Seamless Cross-Platform: Seamless transition, Native code can be wrapped as components usable by React Native

  • Fast Refresh: Changes take effect immediately, having Web-like development speed

So, there are 2 questions:

  • Why use React (or JavaScript) to write Native applications? What's the driving force?

  • Why cross-platform in this way, instead of WebView?

Exploration Approach

There are 2 reasons for using React to write Native applications:

  • React's own advantages: UI predictability from declarative view definitions, complexity decomposition under componentization mechanism, etc.

  • Web development advantages: Fast iteration, fast feedback, fast development

If Native uses React, it can also gain React's various benefits. Of course, this is just one aspect; the real driving force behind is the hope that Native development can move fast like Web.

For the second question, we need to start from the origin of React Native.

Actually, Facebook tried 3 approaches:

  • WebView: Native provides Webview container, business uses Web technology for development

  • Porting React to native: Port React to Native implementation

  • Scripting native: Call Native API through JavaScript

Not using low-cost WebView solution for cross-platform is because limited by Web technology, experience cannot compare with Native, ultimately abandoned because performance and scalability didn't meet expectations.

Porting React to Native is a good approach, but can only gain some of React's own benefits (not including React's prosperous ecosystem in JavaScript world), and doesn't help Native's move fast, because Native is still pure Native.

In comparison, React Native calling Native API through JavaScript is a win-win solution,既能 let Native use React (and JavaScript's prosperous ecosystem), and also have Web's development speed, because what's written and actually executed are both JavaScript, Native only provides view rendering capabilities and platform-specific capabilities.

Development History

React Native was born in 2013 at Facebook's internal hackathon.

At React.js Conf in January 2015, this internal project was first announced, and officially open-sourced at F8 Conference in May. Initially only supported iOS, supported Android in September of the same year.

Microsoft UWP and Samsung Tizen support provided in 2016 means React Native moved from mobile to PC (Win 10), game consoles (Xbox One), smartwatches (Gear Fit 2), smart TVs (SUHD) and even holographic glasses (HoloLens).

Architecture upgrade plan Fabric was launched in June 2018, refactoring thread model and simplifying React Native Core to better support Native & React Native hybrid apps.

JavaScript engine-level performance improvement came in July 2019, replacing JavaScriptCore previously used on Android platform with Hermes.

P.S. For more information about React Native development history, see A Brief History of React Native

II. Architecture: So, This is What RN Is Like!

What you write is JavaScript, what actually renders is Native interface

Therefore, from a very high perspective, React Native technology (or Scripting Native solution) can be understood like this:

JavaScript Layer
---------------------------------
???
---------------------------------
Native Layer

The key point is: What's in the middle? How are the upper and lower worlds connected?

Architecture Design

In React Native, the middle is Bridge layer, connecting JavaScript world and Native world through message communication.

Specifically, Shadow Tree is used to define UI effects and interaction features, Native Modules provide Native capabilities (such as Bluetooth), and they communicate with each other through JSON messages:

Bridge layer is the key to React Native technology, with 3 design characteristics:

  • Asynchronous: Doesn't rely on synchronous communication

  • Serializable: Ensures all UI operations can be serialized to JSON and converted back

  • Batched: Queues Native calls, processes in batches

P.S. For more information about React Native architecture, see React Native Architecture Overview

Thread Model

There are mainly 3 threads in React Native:

  • UI Thread: Main thread in Android/iOS (or other platform) applications

  • Shadow Thread: Thread for layout calculations and constructing UI interface

  • JS Thread: React and other JavaScript code all execute in this thread

Additionally, there's a category of Native Modules threads, different Native Modules can run in different threads (see Threading for details)

Startup Process

Overall, startup process is divided into two parts: initializing Bridge and executing business code, corresponding to upper and lower parts in the diagram:

Rendering Mechanism

During first render (process from right to left in diagram), JS thread passes view information (structure, style, properties, etc.) to Shadow thread, creates Shadow Tree for layout calculations. After Shadow thread calculates layout, it passes complete view information (including width, height, position, etc.) to main thread, which creates Native View based on this.

During user interaction (process from left to right in diagram), main thread first packages relevant information into event messages and passes to Shadow thread, then generates specified events for corresponding elements based on mapping relationship established by Shadow Tree, finally passes events to JS thread to execute corresponding JS callback functions.

Architecture Evolution

Original design also brought some limitations:

  • Asynchronous: Cannot directly integrate JavaScript logic with many Native APIs that need synchronous answers

  • Batched: Very difficult for React Native applications to call functions implemented by Native

  • Serializable: Exists unnecessary copy, instead of directly sharing memory

These problems are especially prominent in Native + React Native hybrid applications, therefore, large-scale architecture upgrade plan was proposed in June 2018:

Specifically includes 3 major changes:

  • JavaScript Layer: Introduce JSI, allowing replacement of different JavaScript engines

  • Bridge Layer: Divide into Fabric and TurboModules parts, responsible for UI management and Native modules respectively

  • Native Layer: Streamline core modules, split non-core parts out as community modules for independent update and maintenance

Fabric expects to simplify complex cross-thread interactions in rendering process, allowing JavaScript to directly control high-priority UI operations, even allowing synchronous calls (handling scenarios like fast list scrolling, page switching, gesture processing, etc.)

TurboModules allows on-demand loading of Native modules, and directly holds their references after module initialization, no longer relying on message communication to call module functions.

P.S. For more information about React Native architecture upgrade, see React Native Architecture Evolution

III. Ecosystem: Learn once, write anywhere?

React Native's original vision is learn once, write anywhere:

It's worth noting that we're not chasing "write once, run anywhere." Different platforms have different looks, feels, and capabilities, and as such, we should still be developing discrete apps for each platform, but the same set of engineers should be able to build applications for whatever platform they choose, without needing to learn a fundamentally different set of technologies for each. We call this approach "learn once, write anywhere."

(From React Native: Bringing modern web techniques to mobile)

Application Ecosystem

In terms of platform support, currently (2019/9/21), besides official Android, iOS support, community also provides UWP, Tizen, Web, Mac, Apple TV, even WeChat Mini Program support.

P.S. For more supported platforms, see Out-of-Tree Platforms

In terms of enterprise applications, besides Facebook, React Native is also used in large-scale enterprises like Tencent, Baidu, JD.com:

Tool Ecosystem

In the 4 years since React Native's development, tool ecosystem has also developed to a certain extent:

P.S. For more information about React Native ecosystem, see Exploring React Native Ecosystem – Tools, backend, database and best libraries

Compared to deeply accumulated Android, iOS technology ecosystems, React Native ecosystem is still at a lower maturity stage, thus facing difficulties like Native infrastructure integration, cross-language stack debugging. But anyway, the vision of Learn once, write anywhere is on the way, coming towards us.

References

Comments

No comments yet. Be the first to share your thoughts.

Leave a comment