1000 千米高空俯瞰 React Native

夢燼發表於2020-05-26

一.歷史:React Native 從開始到現在

React Native 的定位是通過 React 構建原生 App:

A framework for building native apps with React.

具有 5 大特性:

  • Create native apps for Android and iOS using React:用 React 建立 Android、iOS 應用

  • Written in JavaScript—rendered with native code:寫的是 JavaScript,實際渲染的是 Native 介面

  • Native Development For Everyone:基於平臺無關的基礎元件開發,就能獲得平臺原生體驗

  • Seamless Cross-Platform:無縫過渡,Native 程式碼能夠包裝成 React Native 可用的元件

  • Fast Refresh:改動立即生效,擁有 Web 一樣的開發速度

那麼,有 2 個問題:

  • 為什麼要用 React(或者說用 JavaScript)寫 Native 應用?源動力是什麼?

  • 為什麼以這種方式跨平臺,而不是 WebView?

 

探索思路

之所以用 React 寫 Native 應用,有 2 方面原因:

  • React 自身的優勢:宣告式檢視定義帶來的 UI 可預測性、元件化機制下的複雜度拆解等

  • Web 開發的優勢:快速迭代、快速反饋、快速開發

Native 用上 React 的話,也能獲得 React 的種種好處。當然,這只是一方面,背後的真正源動力是希望 Native 開發能像 Web 一樣 move fast

而對於第二個問題,要從 React Native 的由來說起

實際上,Facebook 嘗試過 3 種思路:

  • WebView:由 Native 提供 Webview 容器,業務用 Web 技術來開發

  • Porting React to native:把 React 移植到 Native 實現

  • Scripting native:通過 JavaScript 呼叫 Native API

不利用低成本的 WebView 方案跨平臺,是因為受限於 Web 技術,體驗無法與 Native 相提並論,最終因效能和擴充套件性沒有達到預期而作罷

把 React 移植到 Native 是個不錯的思路,但只能獲得 React 自身的一些好處(不包括 JavaScript 世界的 React 繁榮生態),並且無助於 Native 的 move fast,因為 Native 還是純 Native

相比之下,React Native 通過 JavaScript 呼叫 Native API 是一個兩全其美的方案,既能讓 Native 用上 React(及 JavaScript 的繁榮生態),也能擁有 Web 的開發速度,因為寫的和實際執行的都是 JavaScript,Native 僅提供檢視渲染能力及平臺特定能力

 

發展歷程

React Native 誕生於 2013 年的 Facebook 內部黑客馬拉松(hackathon)

 

 

2015 年 1 月的 React.js Conf 上,這個內部專案首次公佈,並在 5 月的 F8 Conference 上正式開源。最初只支援 iOS,同年 9 月支援了 Android

2016 年提供的 Microsoft UWP 和 Samsung Tizen 支援,意味著 React Native 從移動端走向了 PC(Win 10)、遊戲機(Xbox One)、手環(Gear Fit 2)、智慧電視機(SUHD)甚至全息眼鏡(HoloLens)

2018 年 6 月啟動了架構升級計劃 Fabric,重構執行緒模型並簡化 React Native Core,以更好地支援 Native & React Native 混合 App

2019 年 7 月迎來 JavaScript 引擎級效能提升,將 Android 平臺之前使用的 JavaScriptCore 替換成 Hermes

P.S.關於 React Native 發展史的更多資訊,見React Native 簡史

 

二.架構:原來,你是這樣的 RN!

寫的是 JavaScript,實際渲染的是 Native 介面

因此,從非常高的視角來看,可以這樣理解 React Native 技術(或者說 Scripting Native 方案):

JavaScript層
---------------------------------
???
---------------------------------
Native層

關鍵點在於:中間是什麼?上下兩個世界是怎樣聯絡起來的?

 

架構設計

在 React Native 裡,中間是 Bridge 層,通過訊息通訊將 JavaScript 世界與 Native 世界聯絡起來

具體的,Shadow Tree 用來定義 UI 效果及互動功能,Native Modules 提供 Native 功能(比如藍芽),二者之間通過 JSON 訊息相互通訊:

 

 

Bridge 層是 React Native 技術的關鍵,設計上具有 3 個特點:

  • 非同步(asynchronous):不依賴於同步通訊

  • 可序列化(serializable):保證一切 UI 操作都能序列化成 JSON 並轉換回來

  • 批處理(batched):對 Native 呼叫進行排隊,批量處理

P.S.關於 React Native 架構的更多資訊,見React Native 架構一覽

 

執行緒模型

 

 

React Native 中主要有 3 個執行緒,分別是:

  • UI Thread:Android/iOS(或其它平臺)應用中的主執行緒

  • Shadow Thread:進行佈局計算和構造 UI 介面的執行緒

  • JS Thread:React 等 JavaScript 程式碼都在這個執行緒執行

此外,還有一類 Native Modules 執行緒,不同的 Native Module 可以執行在不同的執行緒中(具體見Threading

 

啟動過程

整體上,啟動過程分為初始化 Bridge 與執行業務程式碼兩部分,對應圖中上下兩部分:

 

 

 

渲染機制

 

 

首次渲染時(圖中自右向左的流程),JS 執行緒將檢視資訊(結構、樣式、屬性等)傳遞給 Shadow 執行緒,建立出用於佈局計算的 Shadow Tree,Shadow 執行緒計算好佈局之後,再將完整的檢視資訊(包括寬高、位置等)傳遞給主執行緒,主執行緒據此建立 Native View

使用者互動時(圖中自左向右的流程),則先由主執行緒將相關資訊打包成事件訊息傳遞到 Shadow 執行緒,再根據 Shadow Tree 建立的對映關係生成相應元素的指定事件,最後將事件傳遞到 JS 執行緒,執行對應的 JS 回撥函式

 

架構演進

最初的設計也帶來了一些限制:

  • 非同步:無法將 JavaScript 邏輯直接與許多需要同步答案的 Native API 整合

  • 批處理:很難讓 React Native 應用呼叫 Native 實現的函式

  • 可序列化:存在不必要的 copy,而不是直接共享記憶體

這些問題在 Native + React Native 的混合應用中尤其突出,因此,2018 年 6 月提出了大規模的架構升級計劃:

 

 

具體包含 3 點重大改動:

  • JavaScript 層:引入 JSI,允許替換不同的 JavaScript 引擎

  • Bridge 層:劃分成 Fabric 和 TurboModules 兩部分,分別負責 UI 管理與 Native 模組

  • Native 層:精簡核心模組,將非核心部分拆分出去作為社群模組獨立更新維護

Fabric 期望簡化渲染流程中複雜的跨執行緒互動,允許 JavaScript 直接控制高優先順序的 UI 操作,甚至允許同步呼叫(應對列表快速滾動、頁面切換、手勢處理等場景)

TurboModules 允許按需載入 Native 模組,並在模組初始化之後直接持有其引用,不再依靠訊息通訊來呼叫模組功能

P.S.關於 React Native 架構升級的更多資訊,見React Native 架構演進

 

三.生態:Learn once, write anywhere ?

React Native 最初的願景是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.”

(摘自React Native: Bringing modern web techniques to mobile

 

應用生態

平臺支援上,目前(2019/9/21),除官方提供的 Android、iOS 支援外,社群還提供了UWPTizenWebMacApple TV,甚至微信小程式等支援

P.S.更多支援平臺,見Out-of-Tree Platforms

企業應用方面,除 Facebook 外,React Native 在騰訊、百度、京東等大規模企業中都有所應用:

 

工具生態

React Native 發展至今的 4 年裡,工具生態也有了一定程度的發展:

P.S.關於 React Native 生態的更多資訊,見Exploring React Native Ecosystem – Tools, backend, database and best libraries

比起積澱深厚的 Android、iOS 技術生態,React Native 生態尚處於較低成熟度的階段,因而面臨與 Native 基礎設施整合、跨語言棧除錯等難題。但無論怎樣,Learn once, write anywhere 的願景在路上,正向我們趕來

 

參考資料

 

相關文章