<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          React Native 新架構(gòu)

          共 3133字,需瀏覽 7分鐘

           ·

          2020-11-24 04:09


          本文轉(zhuǎn)載自知乎專欄前端醬爆,作者章偉東,網(wǎng)易云音樂 前端工程師。

          本文主要介紹FB團(tuán)隊正在重構(gòu)的ReactNative(下面稱RN)新架構(gòu),主要當(dāng)前架構(gòu),Bridge帶來的問題,新架構(gòu),JSI,F(xiàn)abric,TurboModules,CodenGen及LeanCore等概念。

          當(dāng)前架構(gòu)

          RN現(xiàn)在主要有3個線程

          1. JS thread。JS代碼執(zhí)行線程,負(fù)責(zé)邏輯層面的處理。Metro(打包工具)將React源碼打包成一個單一JS文件(就是圖中JSBundle)。然后傳給JS引擎執(zhí)行,現(xiàn)在ios和android統(tǒng)一用的是JSC。

          2. UI Thread(Main Thread/Native thread)。這個線程主要負(fù)責(zé)原生渲染(Native UI)和調(diào)用原生能力(Native Modules)比如藍(lán)牙等。

          3. Shadow Thread。這個線程主要是創(chuàng)建Shadow Tree來模擬React結(jié)構(gòu)樹。Shadow Tree可以類似虛擬dom。RN使用Flexbox布局,但是原生是不支持,所以Yoga就是用來將Flexbox布局轉(zhuǎn)換為原生平臺的布局方式。

          Bridge的問題

          首先回顧一下當(dāng)前Bridge的運(yùn)行過程。

          當(dāng)我們寫了類似下面的React源碼。

          <View?style={{

          ??backgroundColor:?'pink',

          ??width:?200,

          ??height:?200}}

          />

          JS thread會先對其序列化,形成下面一條消息

          UIManager.createView([343,"RCTView",31,?{"backgroundColor":-16181,"width":200,"height":200}])

          通過Bridge發(fā)到ShadowThread。Shadow Tread接收到這條信息后,先反序列化,形成Shadow tree,然后傳給Yoga,形成原生布局信息。

          接著又通過Bridge傳給UI thread。

          UI thread 拿到消息后,同樣先反序列化,然后根據(jù)所給布局信息,進(jìn)行繪制。

          從上面過程可以看到三個線程的交互都是要通過Bridge,因此瓶頸也就在此。

          Bridge三個特點:

          1. 異步。這些消息隊列是異步的,無法保證處理事件。

          2. 序列化。通過JSON格式來傳遞消息,每次都要經(jīng)歷序列化和反序列化,開銷很大。

          3. 批處理。對Native調(diào)用進(jìn)行排隊,批量處理。

          異步設(shè)計的好處是不阻塞,這種設(shè)計在大部分情況下性能滿足需求,但是在某些情況下就會出問題,比如瀑布流滾動。

          當(dāng)瀑布流向下滑動的時候,需要發(fā)請求給服務(wù)端拿數(shù)據(jù)進(jìn)行下一步渲染。

          滾動事件發(fā)生在UI thread,然后通過Bridge發(fā)給JS thread。JS thread 監(jiān)聽到消息后發(fā)請求,服務(wù)端返回數(shù)據(jù),再通過Bridge返回給Native進(jìn)行渲染。由于都是異步,就會出現(xiàn)空白模塊,導(dǎo)致性能問題。

          從上面可以看出,性能瓶頸主要是存在JS線程和Native有交互的情況,如果不存在交互,RN的性能良好。

          因此,對于RN的優(yōu)化,主要集中在Bridge上,有下面3個原則:

          1. JS和Native端不通信。最徹底的方式,消息不走Bridge。

          2. JS和Native減少通信。在兩端無法避免的情況下,盡量通信減少次數(shù)。比如多個請求合并成一個。

          3. 較少JSON的大小。比如圖片轉(zhuǎn)為Base64會導(dǎo)致傳輸數(shù)據(jù)變大,用網(wǎng)絡(luò)圖片代替。

          RN里面可以通過MessageQueue來監(jiān)聽Bridge通信,主要代碼如下

          import?MessageQueue?from?'react-native/Libraries/BatchedBridge/MessageQueue.js';


          const?spyFunction?=?(msg)?=>?{

          ??console.log(msg);

          };


          MessageQueue.spy(spyFunction);

          下面是監(jiān)聽到的信息

          新架構(gòu)

          FB團(tuán)隊逐漸意識到了這些問題,同時也受到Flutter的壓力,在2018年提出了新架構(gòu)

          主要有JSI、Fabric、TurboModules、CodeGen、LeanCode組成。

          JSI

          JSI是整個架構(gòu)的核心和基石,所有的一切都是建立在它上面。

          JSI是Javascript Interface的縮寫,一個用C++寫成的輕量級框架,它作用就是通過JSI,JS對象可以直接獲得C++對象(Host Objects)引用,并調(diào)用對應(yīng)方法

          另外JSI與React無關(guān),可以用在任何JS 引擎(V8,Hermes)。

          有了JSI,JS和Native就可以直接通信了,調(diào)用過程如下:

          JS->JSI->C++->ObjectC/Java

          自此三個線程通信再也不需要通過Bridge,可以直接知道對方的存在,讓同步通信成為現(xiàn)實。具體的用法可以看 官方例子。

          另外一個好處就是有了JSI,JS引擎不再局限于JSC,可以自由的替換為V8,Hermes,進(jìn)一步提高JS解析執(zhí)行的速度。

          Fabric

          Fabric是整個架構(gòu)中的新UI層,包括了新架構(gòu)圖中的renderer和shadow thread。

          下圖是舊的通信模型。

          三個線程通過Bridge異步通信,數(shù)據(jù)需要拷貝多份。

          有了JSI以后,JS可以直接掉調(diào)用其他線程,實現(xiàn)同步通信機(jī)制。另外數(shù)據(jù)可以直接引用,不需要拷貝,于是就變成了下面新的通信模式.

          除了同步能力,直接引用,另外一個好處是Fabric現(xiàn)在支持渲染優(yōu)先級比如React的Concurrent和Suspense模式

          下面兩張圖是從啟動到渲染階段,加入Fabric前后的變化。

          改造為Fabric之后

          TurboModules

          TurboModules主要和原生應(yīng)用能力相關(guān),對應(yīng)新架構(gòu)圖上的Native Modules,這部分的優(yōu)化是:

          1. 通過JSI,可以讓JS直接調(diào)用Native模塊,實現(xiàn)一些同步操作。比如調(diào)用攝像頭能力。

          2. Native模塊懶加載。之前RN框架啟動的時候會加載所有Native模塊,導(dǎo)致啟動慢,時間久。現(xiàn)在有了TurboModules后,可以實現(xiàn)按需加載,減少啟動時間,提高性能。

          CodeGen

          通過CodeGen,自動將Flow或者Ts等有靜態(tài)類型的JS代碼翻譯成Fabric和TurboModules使用的原生代碼。

          Lean Core

          這部分主要是包的瘦身,以前所有的包都放在RN核心工程里面。現(xiàn)在RN核心只保留必要的包,其他都移到react-native-community 或者拆出單獨的組件,比如Webview和AsyncStore。

          當(dāng)前進(jìn)度

          1. JSI已經(jīng)跟隨RN0.59(JSIExecuter.cpp)發(fā)布,但是任然使用Bridge來通信

          2. Fabric和TurboModules還在開發(fā),LeanCore已經(jīng)完成

          3. 現(xiàn)在可以使用C++跨平臺模塊。

          4. 對JS會實現(xiàn)向下兼容,對Native Modules不會兼容。

          5. 具體的進(jìn)度可以參考Fabric進(jìn)度討論和 TurboModules進(jìn)度討論和JSI進(jìn)度討論和CodeGen進(jìn)度討論,以及React官方源碼

          目前RN的新架構(gòu)正在緊張的重構(gòu)中,比預(yù)定的時間表晚了一點,比較期待新框架的發(fā)布和表現(xiàn)。

          參考資料

          1. react-native-fabric-why-am-i-so-excited

          2. How React Native constructs app layouts

          3. React Native — A Bridge To Project Fabric

          4. Chen Feldman - React Native - Under the Bridge

          點個『在看』支持下?

          瀏覽 135
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产不卡视频一卡二卡三卡四卡 | 豆花视频色 | 中文无码在线观看中文字幕av中文 | 黄网免费在线观看 | 欧美操日本 |