日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

庖丁解牛!深入剖析React Native下一代架构重构

發布時間:2023/12/4 综合教程 33 生活家
生活随笔 收集整理的這篇文章主要介紹了 庖丁解牛!深入剖析React Native下一代架构重构 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Facebook在2018年6月官方宣布了大規模重構React Native的計劃及重構路線圖。目的是為了讓React Native更加輕量化、更適應混合開發,接近甚至達到原生的體驗。(也有可能是React Native團隊感受到了Google Flutter的追趕壓力,必須從架構上做出重大革新,未來才有可能和Flutter進行全面的競爭)。

從Facebook公布的官方信息來看,這是一次革命性的架構重構,主要的重構內容如下:

1.改變線程模式。UI 更新不再同時需要在三個不同的線程上觸發執行,而是可以在任意線程上同步調用 JavaScript 進行優先更新,同時將低優先級工作推出主線程,以便保持對 UI 的響應。

2.引入異步渲染能力。允許多個渲染并簡化異步數據處理。

3.簡化JSBridge,讓它更快、更輕量。

目前React Native有哪些問題?

目前業內React Native框架已經有了廣泛的應用。京東在這個方面起步比較早,相對來說整體解決方案也比較成熟。目前京東深度定制和擴展的JDReact解決方案已經累計接入了200+個RN業務和20+的獨立APP,并且承擔了千萬級的DAU。從業務實際開發中還是遇到了不少坑,其中性能問題比較明顯,具體有以下幾類問題:

  • 加載性能偏慢,因為系統或者自定義的原生UI組件和API的注冊加載過程中需要驗證所有屬性和JS API的一致性,影響加載性能,甚至直接導致主UI線程很容易阻塞。

  • JSBridge,React Native整體生命周期和JSBridge綁定太緊,所有的原生和JS之間操作全部是通過這個Bridge,而且每次的事件通訊是有時間間隔的,導致整體渲染過程是異步的。

  • 手勢問題,React Native目前的架構,從JS側很難解決很多復雜的手勢問題,需要重新定制SDK來解決問題。

  • 返回事件的處理,目前的返回事件不能像原生一樣,在組件中監聽。

  • Layout的計算,整體的UI計算必須要在shadow layout中完成,沒有辦法在整體的平臺框架中計算。

現有的Native \u0026amp; JS Component組件如下,通過這些組件可以完成原生UI渲染和API調用。這些組件都是通過packageManger注冊到系統的,當RN業務啟動后,需要對整體的屬性和方法做一些校驗,存在性能損失;另外RN是允許多個packagemanger同時注冊的,當API數量偏大時,導致的問題需要循環遍歷,調用過程也存在性能損耗。

1.Native Modules ,原生端API接口。

2.ViewManager,原生UI組件。

3.Native Navigation,原生導航組件。

4.ComponentKit \u0026amp; Litho,原生端基于yoga UI組件。

5.RCTSurface,原生端Surface實現。
加載過程中首先需要加載初始化React Native Core Bridge,包含以上的一些組件功能,然后才能運行業務的JS Code,只有這步完成后,React Native才能將JS的組件渲染成原生的組件:

所以目前的架構下這些組件和API太過依賴JSBridge的初始化,而且通訊能力也局限于這一條通道。從渲染的層次來看,React Native是多線程運行的,最常見的是JS線程和原生端的線程,一旦線程間異常,JSBridge整體將會阻塞,我們經常也能看到JS運行異常了,實際JS線程已經無響應了,但原生端還能響應滾動事件。

如何徹底解決這些問題?

針對先有框架的一些問題Facebook在最近的版本中嘗試過很多優化工作,從2013年發布到目前已經更新到了V0.58,去年一年發布了10多個版本。從版本更新可以看出,除了一些組件的更新和BUG修復外,Facebook做了性能優化方面的嘗試,讓其在加載和渲染性能上盡可能的達到原生。

重大性能優化的版本:

  • 0.33 Lazy module

  • 0.40 RAM bundle/unbundle

  • 0.43 FlatList/SectionList/VirtualizedList

  • 0.50 SwipeableFlatList/Fiber

以下是目前官方建議的一些優化性能的方案:

1.組件的懶加載注冊,原生端可以采用懶注冊,在業務使用到該組件時注冊。

2.按需打包,直接減少業務包大小,去掉一些不需要的module,提高渲染速度。

3.業務的懶加載,直接減少業務渲染過程中require各個組件的時間。

4.UNBundle,將業務分解成小的模塊,提供性能。

5.移走初始化過程中不必要的JS module模塊。

6.提供prepack工具優化JS代碼。

最新的架構又提出了Fibe/Relay Modern架構,整體渲染性能相比以前有了很大的提高,最新的JDReact SDK已經升級到這個架構,目標是將加載JSBridge的開銷降到最低,但是文章前面提到的瓶頸問題還是沒有突破。

我們和跨端平臺框架Flutter啟動和渲染做了對比,在啟動性能上React Native稍微優于Flutter,但渲染方面明顯不如Flutter,也就是我們說的瓶頸問題,對比如下圖:

所以,我們的結論是,在現有架構下的各種優化都很難徹底解決性能問題。

唯有架構重構才是王道

在最近的開發者大會中,Facebook對下一代架構重構的進展進行了介紹,我們也對master分支上提交的部分源碼進行了分析,可以了解新架構的一些雛型設計,整體架構還在不斷優化中,相信還會有更多驚喜。從現有的信息和代碼來看,JS層業務的影響較小,不會因此次大規模架構重構后需要大量適配業務代碼。這次的重構主要是JSBridge及原生架構的重構,下面我們從幾個層面對比介紹整體框架:

現有架構渲染原理

UI的渲染過程分為三層:JS業務層、shadow tree、原生UI層。其中JS和shadow tree是通過JSBridge來同步數據的,JS層會將所有UI node生成一串JSON數據,傳遞到原生shadow層,原生shadow層通過傳入node數據,新增新UI或者刪除一些不需要的UI組件,這就完成了下圖這三個層次之間的驅動關系:

帶來的問題是整體UI渲染異步且太過于依賴JSBrige,很容易出現阻塞而影響整體UI體驗,從JDReact的業務開發經驗來看,比如初始化過程中UI復雜度過高,點擊UI時響應時間會很長,就是因為UI被阻塞了很難響應touch事件,另外UI大小計算JS framework沒有辦法直接計算,需要依賴原生計算完成后的回調。

再看看SrollView的例子,這是業務或者社區反饋性能和體驗問題最大的組件。最初版本的ScollView是一次渲染的不作任何回收,所以啟動性能慢且內存占用較大。后續版本Flatlist作了組件的回收,內存基本穩定了,但是快速滑動過程中出現了體驗問題,容易白屏且容易卡頓。大家看下面的流程圖就能明白為什么Flatlist(基于ScollView實現)/ScrollView 快速滑動下會有長時間的白屏或者卡頓。

在Flatlist快速滑動過程中JS層會根據滑動的事件,觸發Flatlist item的render渲染每一條數據,但是因為JSBridge的異步關系導致了shadow層最終呈現到原生的UI是異步的,而且滑動太快后會有大量的UI事件會阻塞在JSBridge,也導致了長時間的白屏出現,同時當部分item滑出可視區域一定的范圍后UI內容會被回收等待下次滑到該區域后重新渲染。

新架構Fabric渲染原理

回到之前ScrollView的例子,看看Fabric是怎么解決快速滑動過程中的性能問題的。

1.初始化:JS到Shadow層已經是同步操作了,而shadow層到原生UI變成了可以異步也可以同步操作了,組件可以根據自己的業務場景來適配不同的操作。

2.滑動過程:原生端直接控制JS層渲染,同時創建shadow層的node節點,node節點會采用同步的方式渲染原生UI,整個過程中滑動的渲染是采用的同步操作,所以不會出現舊架構下白屏的問題。

Fabric –新的UI架構

1.React Fabric Renderer (JS) ,JS端的Render架構。

2.FabricUIManager (JS, C++) ,JS端和原生端UI管理模塊。

3.ComponentDescriptor (C++) ,原生端組件的唯一描述及組件屬性定義。

4.Platform-speci?c Component Impl (ObjC++, Java) ,原生端組件。
RCTSurface (ObjC++, Java),Surface組件。

從這些組件的結構描述來看,新的Fabric架構大致如下:

1.shadow層從原有的Java層,挪到了C++層。

2.由C++層來管理整體的UI組件,原有的Java層UIManager換到C++層,管理這些C++層到虛擬組件。

3.而原生的組件透過JNI層會在C++層生成對應的實例,綁定一些屬性和方法。

4.JS層FabricUIManager透過JSI,喚起C++層去生產node節點,并最終對應到我們的ComponentDescriptor。

從整體來看JS端的node節點可以完整的和C++端的node節點一一對應,透過JSI可以完成同步的調用和屬性同步,同樣C++到原生java層到組件是通過JNI來完成的,而且也是同步操作。

下面我們參考下目前Facebook開放出來的部分代碼:

1.ComponentDescriptor,原生和原生UI對應的一層抽象層,這邊實現了原生端組件的屬性和事件,并通過唯一標示注冊到comonentRegister中,以下是已經開放出來的switch組件的代碼架構。

ComponentDescriptor組件

整體的Fabric的UIManger 組件和消息通道是怎么建立的呢?大家可以參考文件Scheduler.cpp,JS會通過JSI調用該接口來初始化。

1.Fabric component 注冊。

2.消息通道注冊。

3.初始化UIManager和UIManagerbinding,其中UIManager提供了創建node、clone node,添加shadow node、關閉surface等功能,而UIManagerbinding是基于JSI接口直接實現了和JS端UIManger的直接調用,大家可以參考源碼JS端是通過JSI的get方法,通過屬性的方式通知UIManagerbinding執行C++層的UIManger,而UImanger最終會根據生成的shadow node生成對應的UI。

Fabric UI架構初始化

下面我們看看JS端是如何生成原生組件的,大家可以對照源碼,在JS端我們有FabricUIManager,在初始化UIManagerBinding過程中,注冊到運行的JS環境,因為UIManagerBinding是JSI實現的,所以可以理解為我們創建了一個Host代理對象,注冊到了JS,而JS側也對應同樣的數據結構來一一對應。

下面是創建一個node的列子:

從目前的結構來看,后續Fabric UI開發,需要從C++ component層、shadow層、原生Java層,三個層次開發,而且創建的shadow層也是通過JSI的方式和JS層的node節點一一對應的。

JS端測量大小

JSI介紹

上面介紹Fabric架構時提到了JSI,那到底什么是JSI呢?如何能做到更原子級的控制每個模塊和API呢?他是架起JS和原生java或者Objc的橋梁,類似于現有架構的JSBridge,但是采用的是內存共享、代理類的方式,JSI所有的運行環境都是在JSCRuntime環境下的,為了實現和JS端直接通訊,我們需要在C++層實現一個JSI::HostObject,該數據結構只有get、set兩個接口,通過prop來區分不同接口的調用。

然后通過JSI接口生成一個JSObject,可以看到生成的代理對象和我們的HostObjectProxy是共享內存的,并且proxy中也實現了set和get方法。以下是具體的流程:

在JS端對應的是LazyObject,通過對這些Object的set、get,來完成對應C++實現的hostobject方法的調用:

TurboModule架構

這是基于新的JSI架構實現的Native module架構。JS層通過JSI獲取到對應的C++層的module對象的代理,最終通過JNI回調Java層module。

C++層NativeMoudleProxy是通過JSI實現的對象,可以通過它傳入module的名字獲取C++層注冊的module,已經這個module封裝的所有的API method name。所以在JS業務加載的時候,會將這個proxy生成JS object代理對象到JS層。

JS層通過getNativeModule API并傳遞prop到JSI,最終會通過JSI接口找到Host object NativeModuleProxy,因NativeModuleProxy主要作用是將注冊在C++層的JSI module通過名字生成JS Object傳遞的JS層調用, 所以其get方法中只有一個屬性,就是通過JSINativeModules獲取對應的module,而JSINativeModules是有緩存機制的,如果沒有緩存的就直接解析該module中所有的API,如果有直接讀取緩存的module信息。

大家可以看到在解析過程中,新版本增加了同步和異步的方法,也就是promise和sync。所以JSI module實際是可以同步操作API的,不像之前JSBridge的API都是異步操作的,同步操作的好處就是能做到線程間的同步。

所有的JSI module都是通過JSIMoudleregistry來注冊的,當然這里注冊的都是C++層的moulde,而所有的C++module最終是通過descriptor綁定到java層的turbomoudle中注冊的Java層module,也就是我們最終在原生端實現的API,所以C++層module會通過對應的method prop來觸發Java層的方法調用。

而C++層Native module是在java層instance manger初始化過程中注冊的,遍歷并注冊java層和C++module。

所有理解Native Module的調用實際就是JSI的調用,而運行返回結果是基礎的數據類型或者JSI object的,所以一個turbo module的method調用,返回值是可以是JSI object。開發者可以根據自己業務需要,將一些完整的數據結構封裝成JSI host object,這樣就可以做到,JS端同樣可以獲取到該對象,并同原生端對象形成了代理關系,可以同步完成一系列該Object porp功能操作,舉個例子:

以前的調用方式通過JSBridge獲取到一個picture,這個數據類型對應到JS端只能是一些基礎的數據類型,比如我們參見的圖片地址String類型,所以如果現在要上傳這個圖片的話,我們將JS端的數據再回傳到原生端,如下圖:

但有了JSI后就不一樣了,我們在JS端透過JSI獲取到的是JS Object,也就是picture,但是這個picture不再是簡單的數據類型,而是和原生端形成綁定關系的結構,能夠支持很多屬性的同步設置,如改變alpha值等等,會直接觸發host object的屬性和函數調用,所以我們不再需要像之前一樣改變alpha需要很多的JSBridge的調用,同樣上傳過程可以直接操作c++層的Object執行上傳操作。

下面簡單列舉一下相關層次的調用關系:

社區化

React Native 目前有52個直接依賴包,然后這些包間接遞歸依賴了589個包,大家可以在http://npm.anvaka.com/#/view/2d/react-native網站看看整體的依賴關系,是一個非常復雜的關系圖。

從目前React Native開源的代碼來看,整體是個很大的repo工程,包含了各種各樣的Native組件、API、JS module,如何讓這些組件和API維護更簡單,讓接入React Native架構的APP能將API或者組件快速裁剪變小也成了這次架構重構的目標。

  • 刪除掉一些不需要的modules,將所有的module分離成小的repo,類似于組件化模塊。

  • 減小業務開發的bundle代碼的大小(按需引入和編譯需要的component),進而提升業務的渲染和啟動速度。

  • 分離后將這些組件或API開放給社區,社區可以貢獻自己的資源,這樣可以讓組件的維護和迭代更快,幫助減少組件維護成本。

  • 減少目前React Native SDK開發的依賴,簡化代碼結構,讓SDK升級起來更輕量、更快速。

  • 增加了社區的貢獻讓PR的修復加快,讓更多的開發者集中在更合理的位置,減少重復開發,降低開放的復雜度。

未來facebook計劃:

1.刪除所有覺得使用率低或者無價值的組件或者API。

2.將現有維護的模塊移到外部的repo,單獨維護。

具體組件的規劃和歸類,大家可以同步參考Facebook提供的列表,有很多組件已經明確要刪掉或者移到開源社區來,比如WebView。

以下是React Native組件社區的規劃圖:

以后原生端Native組件主要分三部分,一部份會放到系統的SDK,一部分移到開源社區維護,開發者再貢獻一部分組件。對開發者而言帶來的影響:

1.所有組件不能像之前一樣一次就同步下來了,需要根據拆分的repo由開發者自己按需安裝repo,碎片化比較嚴重。

2.因為社區運營后開發者貢獻會越來越快,版本迭代也會加速,所以版本的控制和代碼的安全性也是一個重要的問題。

3.很多社區化的組件是對原生Native module是有依賴的,所以增加了前端開發人員的集成開發難度。

總結

我們通過源碼分析給大家簡單介紹了Facebook的React Native下一代框架的設計,相信不管從性能體驗和功能上都會有很大的變化。雖然整體變化很大但對于前端開發者而言JS的變化微乎其微,而重點改造在原生端組件和API架構,封裝起來變得更加復雜,需要封裝C++ shadow層,所以從以前的JAVA開發擴展到了C++和JAVA開發,對于開發者知識結構和儲備要求更高,但對于提升性能而言,這些都是值得的。

社區化運營后Facebook官方可以從以前的組件和框架一起開發,簡化到只需關注整體框架能力和性能了,讓開發者貢獻維護現在組件,大大提高了框架的迭代周期。

京東多端融合技術團隊也會持續保持關注,待React Native新架構穩定后也會對渲染引擎進行升級并引入新的架構和特性。未來也會打通JDReact和JDFlutter雙引擎的底層和組件,提供更為全面的跨端解決方案。

更多內容,請關注前端之巔。

總結

以上是生活随笔為你收集整理的庖丁解牛!深入剖析React Native下一代架构重构的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。