Faster than faster——RN新架構中的JavaScript Interface

背景

隨着Flutter等新框架的崛起,React Native正經受着愈來愈大的挑戰,RN性能上的瓶頸愈發明顯。爲了在與Flutter等框架的對抗中保持競爭力,RN醞釀在架構上進行了一次很是大的升級。因而,在一篇ReactConf 2018的演講 React Native's New Architecture 中,RN官方向咱們引出了三個新的概念:JSI,Fabric和TurboModule。隨後在2019年第一季度,RN開發人員@kelset 寫了一篇從高層設計上解釋RN爲什麼如此架構的文章: formidable.com/blog/2019/j…。下面就讓咱們來看一看RN是怎麼解決性能瓶頸問題的。node

現有的問題

RN老的架構很是重的依賴於Bridge:git

RN-bridge

全部的JS和Native之間傳遞的信息,都要序列化爲JSON以後進行異步傳輸。這樣就形成一個比較常見的性能問題:快速滑動ListView的時候會白屏,以下圖:github

ListView白屏

如今有三個線程:Native的UI線程,Layout線程和JS線程,他們之間的通訊是異步的。當ListView向上滑動,須要展現新的Cell的時候,Native異步通知到JS線程,JS線程作相應的業務邏輯處理以後,先是異步給到Layout線程,計算Cell的實際顯示區域,以後Layout線程再將算好的結果異步給到Native線程進行UI繪製,因爲滑動很快,這樣就形成UI得不到及時的更新,顯示成白屏。瀏覽器

要解決這個問題,咱們看一看在瀏覽器裏,ListView是怎麼作到沒有白屏的問題的。服務器

瀏覽器ListView

瀏覽器返回的node裏,是有指向C++實際生成的對象的引用的,因此說,JS向瀏覽器裏的調用是同步調用,天然就不會有白屏的問題。網絡

一樣的思路,咱們若是去掉這個異步的bridge,JS和Native同時持有一個HostObject,那樣就能夠進行JS和Native之間的同步調用了,這裏就引伸出了bridge的替代者——JavaScript Interface (JSI)。架構

JavaScript Interface (JSI)

JSI是一個精簡通用型的JS引擎接口,理論上能夠對接任何JS引擎,包括Google的V8和微軟的ChakraCore,或者是RN如今使用的JavaScriptCore(JSC)的新版本(JSI已經集成到RN的0.59版本中,而且在該版本中升級了JSC的版本)。框架

同時,JSI是架起 JS 和Native之間的橋樑,經過在C++層實現一個 JSI::HostObject,如今不須要序列化成JSON並雙向傳遞等一系列操做,實現了Native和 JS間的直接通信。異步

JSI

JSI下的ListView滑動

JSI ListView滑動

虛線是異步調用,實現是同步調用。性能

首先咱們RunApplication,以後異步render,而後再異步到UI線程更新View。在JSI出現以前,這是咱們Native和JS交互的惟一處理方式。

如今UI線程有一個網絡請求更新state的回調,緊接着在UI線程有一個列表的onScroll事件,顯然,這個onScroll事件是咱們急需處理的任務。有了JSI,咱們就能夠同步的處理這個onScroll的任務,更新相應的Native View,就不會有白屏的問題出現。處理完這個緊急的任務,主線程能夠繼續處理網絡請求回調的任務了。

JSI下的Native Modules

JSI同時是Native Modules重構(即TurboModules)的基石。好比如今有一個需求,在RN中拍照並向服務器上傳圖片。在JSI出現以前,咱們須要在JS和Native之間,反覆序列化來傳遞數據,低效且毫無必要:

Native Modules call old

在有了JSI以後,JS和Native同時持有一個HostObject,獲取到圖片以後,捨去了沒必要要的數據傳遞,直接繼續完成上傳的操做。

Native Modules call new

Reference

React Native's New Architecture

formidable.com/blog/2019/j…

相關文章
相關標籤/搜索