基于拆分包的React Native在iOS端加載性能優(yōu)化

自從Facebook于2015年在React Conf大會(huì)上推出React Native,移動(dòng)開發(fā)領(lǐng)域就掀起了一股學(xué)習(xí)與項(xiàng)目實(shí)踐的熱潮。ReactNative不僅具有良好的Native性能,更具備web快速迭代的能力。這兩大特性使得React Native在推廣的過程中順風(fēng)順?biāo)以趪?guó)內(nèi)互聯(lián)網(wǎng)公司的應(yīng)用比國(guó)外還火熱。58 APP從2016年就開始基于ReactNative進(jìn)行項(xiàng)目實(shí)踐,并已經(jīng)對(duì)外進(jìn)行了一些分享。目前項(xiàng)目已進(jìn)入React Native深度研究與實(shí)踐階段。

在ReactNative深度實(shí)踐的過程中,一個(gè)關(guān)鍵的問題是React Native頁面的加載性能。如果不對(duì)這部分進(jìn)行處理,在低端機(jī)上很容易出現(xiàn)短暫的空白,影響用戶體驗(yàn)。在React Native加載性能優(yōu)化方面,業(yè)界已經(jīng)有了一些討論和解決方案,但在針對(duì)問題解決的系統(tǒng)性和可操作性方面還有所欠缺。

本文將基于主流的拆分包思想,系統(tǒng)性地介紹我們?cè)趇OS端處理React Native加載性能問題的經(jīng)驗(yàn),以期給同行提供一些借鑒,避免重復(fù)趟坑。

拆分包實(shí)現(xiàn)方案一:為什么要拆分包:基于完整JSBundle加載存在的問題

58同城具體將React Native應(yīng)用在項(xiàng)目中大概是2016年初,當(dāng)時(shí)主要參考的資料是FaceBook提供的React Native文檔以及官方Demo。按照文檔的理解,創(chuàng)建RN頁面的只需要?jiǎng)?chuàng)建對(duì)應(yīng)的RCTRootView并將其添加到對(duì)應(yīng)的Native視圖中即可,因?yàn)镽CTRootView是一個(gè)UIView的容器,它承載著React Native應(yīng)用,因此如何創(chuàng)建RCTRootView成為了解決問題的關(guān)鍵。根據(jù)根據(jù)官方API,如下圖1所示:

圖1RCTRootView API

從API文檔可以看出,創(chuàng)建RCTRootView必須創(chuàng)建對(duì)應(yīng)的RCTBridge,RCTBridge是JS與Native通信的橋梁,因此問題的關(guān)鍵轉(zhuǎn)化為了如何創(chuàng)建RCBridge。查看React Native源碼發(fā)現(xiàn),如下圖2所示:

圖2 RCTBridge API

從API的接口可以看出,參數(shù)中的bundleURL既可以是遠(yuǎn)程服務(wù)器具體的、完整的、可執(zhí)行的jsbundle的地址,也可以是本地完整的jsbundle對(duì)應(yīng)的絕對(duì)路徑,那么該如何選擇使用哪種bundleURL?

首先對(duì)比下兩種bundleURL優(yōu)缺點(diǎn):

1、就讀取jsbundle文件耗時(shí)而言。讀取遠(yuǎn)程服務(wù)器的jsbundle首先要建立網(wǎng)絡(luò)連接,然后再讀取jsbundle文件,而且依賴用戶當(dāng)時(shí)的網(wǎng)絡(luò)環(huán)境狀況,增加了不穩(wěn)定性,顯然使用本地bundleURL在時(shí)間方面更具優(yōu)勢(shì)。

2、就實(shí)現(xiàn)jsbundle文件熱更新成本而言。遠(yuǎn)程服務(wù)器中的bundleURL可以實(shí)時(shí)更新不依賴native的發(fā)版。而使用本地的bundleURL,若要實(shí)現(xiàn)實(shí)時(shí)更新則需要一套完整的熱更新平臺(tái)支持。顯然遠(yuǎn)程服務(wù)器的bundleURL更具優(yōu)勢(shì)。

3、就用戶的使用APP成本而言。遠(yuǎn)程服務(wù)器的bundleURL在每次進(jìn)入RN頁面時(shí)都會(huì)消耗流量,而本地bundleURL則不需要消耗用戶流量或者僅僅在用戶第一次加載RN頁面的時(shí)候消耗流量,減少用戶的使用成本。顯然就用戶使用成本而言本地bundleURL更具優(yōu)勢(shì)。

綜上所述,使用本地的bundleURL能更好的減少讀取本地JSBundle時(shí)間以及用戶使用APP的成本,提高用戶體驗(yàn),增強(qiáng)用戶黏性。

但是隨著使用React Native業(yè)務(wù)場(chǎng)景的增多,RN頁面數(shù)量也隨之增加,與之對(duì)應(yīng)的是JSBundle文件增多。復(fù)雜的業(yè)務(wù)邏輯也會(huì)導(dǎo)致JSBundle體積越來越大,最直接影響就是App size增大。以實(shí)際數(shù)據(jù)為例:

一個(gè)ReactNative頁面對(duì)應(yīng)的完整JSBundle文件一般為700KB,如果項(xiàng)目中存在300個(gè)React Native頁面則需要內(nèi)置的資源就會(huì)增加210MB(700KB*300),顯然這是無法接受的!因此如何減少內(nèi)置資源體積大小是當(dāng)時(shí)制約React Native能否應(yīng)用到項(xiàng)目中的一個(gè)關(guān)鍵因素。在此背景下引出了引出了方案一的設(shè)計(jì),首先了解下方案一的拆包思想。

拆分包基本思想:

通過分析各ReactNative頁面的JSBundle文件發(fā)現(xiàn)一個(gè)完成的ReactNative頁面代碼結(jié)構(gòu)可以分為模塊引用、模塊定義、模塊注冊(cè)三部分。其中模塊引用主要是全局模塊的定義,模塊定義主要是組件的定義(原生組件、自定義組件),模塊注冊(cè)主要是初始化以及入口函數(shù)的執(zhí)行。

通過對(duì)比發(fā)現(xiàn),不同的JSBundle文件包含著大量重復(fù)的代碼,那么試想下能否通過優(yōu)化打包腳本來對(duì)JSBundle進(jìn)行優(yōu)化,將框架本身的內(nèi)容從完整的JSBundle中抽離出來只剩下純業(yè)務(wù)的JSBundle文件,等到真正需要加載React Native頁面的時(shí)候再將業(yè)務(wù)的JSBundle文件與重復(fù)的JSBundle文件進(jìn)行合并,生成一個(gè)完成的、可執(zhí)行的完整的文件,然后進(jìn)行加載。事實(shí)證明這種方案是可行的,也即是項(xiàng)目中使用的拆分方案JSBundle的拆分與合并,簡(jiǎn)單來講如下圖3、圖4所示:


圖3
圖4

圖3 FE拆分 圖4 Native合并

簡(jiǎn)單解析一下這兩個(gè)圖:

JS端拆分:在打包階段,通過特定的策略將一個(gè)完整的JSBundle拆分成兩個(gè)JSBundle。

Native端合并:Native端通過文本處理,將Common部分的JSBundle與業(yè)務(wù)部分的JSBundle合并成一個(gè)文件。

拆分包實(shí)現(xiàn)方案一

基于以上拆分包的思想,我們可以得出所謂拆分方案就是JS端將完整的JSBundle文件通過腳本拆分為Common.jsbundle文件和Bussiness.jsbundle文件。Common.jsbundle文件是指包含React Native基礎(chǔ)組件以及相關(guān)解析代碼的JS文件,Bussiness.jsbundle文件是指包含業(yè)務(wù)代碼的JS文件。Native端通過內(nèi)置或者熱更新平臺(tái)下發(fā)的方式獲取Common與Bussiness文件,待真正需要展示React Native頁面時(shí)通過合并的方式生成一個(gè)完整的JSBundle文件并加載

JS 端如何實(shí)現(xiàn)的拆包

首先我們了解下JS端如何進(jìn)行jsbundle文件的拆分?整體流程如下圖5所示:

圖5 FE端JSBunlde拆分整體流程

1、如何獲取common.jsbundle文件。

  1. a)首先通過React Native提供的指令react-nativeinitAwesomeProject 來創(chuàng)建一個(gè)空的工程

  2. b)然后根據(jù)WBRN打包平臺(tái)生成jsbundle文件,由于該文件不包含任何業(yè)務(wù)代碼,所以該文件就是所需要的common.jsbundle文件。具體使用的指令如下:react-native bundle--entry-file ./index.ios.js --dev false --bundle-output common.bundle--bundle-encoding utf-8 --platform "ios" 。

2、如何獲取bussiness.jsbundle文件。

  1. a)首先,不同的React Native頁面通過WBRN打包平臺(tái)生成不同的、完整的complete.jsbundle文件。

  2. b)其次,通過Google提供的google-diff-match-patch算法,將complete.jsbundle與common.jsbundle文件進(jìn)行對(duì)比,最終由WBRN打包平臺(tái)輸出兩者的差異的描述文件,也即是bussiness.jsbundle文件。

JS 端的JSBundle 是如何存儲(chǔ)Native 端的?

根據(jù)不同業(yè)務(wù)場(chǎng)景需要,通過WBRN熱更新平臺(tái)為不同的bussiness.jsbundle其配置相關(guān)參數(shù)信息,例如:版本號(hào)、是否需要強(qiáng)制更新APP、是否執(zhí)行下次生效策略、jsbundle下載地址等參數(shù)。

然后通過熱更新平臺(tái)下發(fā)至Native端,整體流程如下圖6所示:

圖6 JSBundle下發(fā)Native整體流程

Native端每次進(jìn)入React Native頁面時(shí)向WBRN熱更新平臺(tái)請(qǐng)求當(dāng)前bussiness.jsbundle的最新信息,若需要更新,則下載最新的diff并將其保存在本地,以確保本地存儲(chǔ)的是最新的jsbundle文件。具體的流程如下圖7所示:

圖7 JSBundle下發(fā)Nativex詳細(xì)流程

1、根據(jù)當(dāng)前bussiness.jsbundle的版本號(hào)、BundleId等參數(shù)請(qǐng)求WBRN熱更新平臺(tái),獲取當(dāng)前bussiness.jsbundle文件的最新信息。

2、根據(jù)返回的信息判斷是否包含commonUrl來判斷是否需要更新common.jsbundle文件,若需要,則下載最新common.jsbundle并保存在沙盒中同時(shí)更新common文件對(duì)應(yīng)的配置文件。若不需要,則common.jsbundle不做任何操作。

3、根據(jù)返回的信息中jsbundle的版本號(hào)與本地jsbundle的版本進(jìn)行比較,判斷是否需要更新bussiness.jsbundle,若需要,則下載最新的bussiness.jsbundle并保存在沙盒中同時(shí)更新該bundle對(duì)應(yīng)的配置文件,否則不執(zhí)行任何操作。

4、根據(jù)返回的信息中isForceUpdate來判斷bussiness.jsbundle是否需強(qiáng)制更新,若需要,則立即生效并展示新的頁面。否則,展示舊頁面,實(shí)行下次生效策略。

注意:

1、在common.jsbundle需要更新的情況下,無論business.jsbundle是否需要強(qiáng)制更新都直接展示最新的頁面。

2、如果本地不存在對(duì)應(yīng)的buniness.jsbundle文件,則下載對(duì)應(yīng)的business.jsbundle后,無論最新信息是否為強(qiáng)制更新則都展示最新的頁面。否則在非強(qiáng)制更新情況下展示舊的頁面。

3、如果bussiness.jsbundle下載失敗,出于用戶體驗(yàn)的角度,如果本地存在舊的bussiness.jsbundle文件,則先展示舊的頁面。

最終,Native端通過熱更新平臺(tái)或者內(nèi)置的方式將Common.jsbundle文件以及bussiness.jsbundle文件存儲(chǔ)在Native本地,存儲(chǔ)的目錄結(jié)構(gòu)如下圖8所示:

圖8 JSbundle本地存儲(chǔ)目錄

從上圖可以看出,存儲(chǔ)在沙盒中的文件不僅包含common.jsbundle和bussiness.jsbundle而且包含兩個(gè)plist文件,其中JSBundleIndex.plist文件就是上文提到的bundle配置文件,用于記錄每個(gè)本地jsbundle對(duì)應(yīng)的版本號(hào),每次與WBRN熱更新平臺(tái)的最新jsbundle文件版本號(hào)進(jìn)行比對(duì),從而判斷是否需要進(jìn)行更新當(dāng)前bussiness.jsbundle。BundleExcepion.plist文件用于記錄每個(gè)本地jsbundle文件對(duì)應(yīng)的異常次數(shù),一旦某個(gè)bussiness.jsbundle文件異常次數(shù)超過一定的閾值,則會(huì)啟動(dòng)看門狗策略,刪除本地相應(yīng)的bussiness.jsbundle文件,再次進(jìn)入React Native頁面時(shí)從服務(wù)器下載最新的bunssiness.jsbundle文件,以確保不會(huì)因?yàn)閖sbundle文件的損害導(dǎo)致頁面一直加載異常。

Native 端如何實(shí)現(xiàn)的合包

通過以上步驟就完成了React Native頁面FE端JSBundle文件的拆分和分發(fā),那么Native端如何使用拆分后的文件呢?關(guān)于Native加載React Native頁面整體的詳細(xì)流程如下圖9所示:

圖9 JBundle加載流程

1、根據(jù)跳轉(zhuǎn)協(xié)議中的bundleId進(jìn)入到對(duì)應(yīng)的載體頁。

2、通過緩存管理模塊檢測(cè)本地沙盒中是否包含bundleId對(duì)應(yīng)的bussiness.jsbundle文件。若存在,則從本地讀取對(duì)應(yīng)的bussiness.jsbundle文件,并通過Google-diff-match-patch算法將common.jsbundle文件與bussiness.jsbundle文件進(jìn)行合并,生成對(duì)應(yīng)的complete.bundle文件,若不存在,則檢測(cè)內(nèi)置中是否含有該bunssiness.jsbundle文件,如果存在,則先執(zhí)行步驟三,否則執(zhí)行步驟四。

3、然后通過JSBundle加載管理模塊讀取complete.bundle文件,加載并展示。

4、若沙盒中和內(nèi)置中均不存在bussiness.bundle文件,則通過jsbundle網(wǎng)絡(luò)管理模塊從服務(wù)器下載bussiness.bundle保存到本地沙盒同時(shí)記錄其版本號(hào),重復(fù)進(jìn)行第二步驟。

5、同時(shí)向服務(wù)器請(qǐng)求當(dāng)前bussiness.bundle的最新信息,根據(jù)返回內(nèi)容來判斷是否需要強(qiáng)制更新頁面,如果不需要強(qiáng)制更新則后臺(tái)下載并執(zhí)行下次生效的策略,否則立即刷新當(dāng)前頁面。

6、如果當(dāng)前頁面已經(jīng)是最新頁面,則不做任何操作。

方案一數(shù)據(jù)對(duì)比:

假設(shè)完整的頁面共600KB,其common.jsbundle大小為531KB,bussiness.bundle大小為70KB。以100個(gè)ReactNative頁面而言,如果不使用拆分包邏輯,需要(531KB+70KB)KB100=60M空間。使用拆分包方案一后,10070KB+531KB=7.5M,節(jié)省空間為87.5%

方案一仍需要解決的問題

從上圖可以得看出,使用方案一優(yōu)化后,同樣數(shù)量的React Native頁面減少的87.5%的存儲(chǔ)空間。但相對(duì)于未拆分方案其增加了兩次I/O操作以及一次文件的合并操作,增加了時(shí)間消耗。高端機(jī)上增加的這部分時(shí)間消耗不太影響用戶體驗(yàn),低端機(jī)設(shè)備則會(huì)出現(xiàn)短暫的空白頁面,影響了用戶體驗(yàn)。那么是否存在一種方案可以在拆包的前提下減少JSBundle的I/O次數(shù)呢,從而減少JSBundle文件的讀取時(shí)間,答案是肯定的,也即是接下來將要介紹的方案二。

拆分包實(shí)現(xiàn)方案二

在引入方案方案二之前首先有必要了解下React Native的整個(gè)加載過程,根據(jù)FaceBook提供的一篇文章,可以看出ReactNavtive從加載到渲染完成主要包括以下六個(gè)階段,如下圖11所示:

圖11 ReactNavtive加載整體過程

1、Native Initialization階段:主要初始化Java虛擬機(jī)和所有后備模塊(磁盤緩存,網(wǎng)絡(luò),UI管理器等)。

2、JS Init + Require 階段:從磁盤讀取最小化的Java軟件包文件,并將其加載到Java虛擬機(jī)中,該虛擬機(jī)將解析它并生成字節(jié)碼,因?yàn)樗枰跏寄K(大多數(shù)為React,Relay及其依賴項(xiàng))。

3、Before Fetch 階段:加載并執(zhí)行事件應(yīng)用程序代碼,構(gòu)建查詢并啟動(dòng)從磁盤緩存讀取數(shù)據(jù)。

4、Fetch階段:從磁盤緩存讀取數(shù)據(jù)

5、JS Render階段:實(shí)例化所有React組件,并將它們發(fā)送到本地UI管理器模塊進(jìn)行顯示。

6、Native Render:通過計(jì)算陰影線程上的FlexBox布局來計(jì)算視圖大小; 在主線程上創(chuàng)建和定位視圖。

上圖清晰的記錄了每個(gè)階段占用時(shí)間的百分比,所以可以直觀的看出耗時(shí)最多的是js init+ require階段,也即是jsbundle的加載和執(zhí)行階段。

因此如何縮短js init+ Require時(shí)間是提高RN頁面展示速度的關(guān)鍵也即是方案二所要解決的問題。接下來詳細(xì)分析下React Native load JSBundle和執(zhí)行JSBundle文件的過程:如下圖12所示:

圖12 JSBundle 加載代碼片段

以上是React Native框架load JSBundle的相關(guān)代碼片段,從上圖代碼中可以看出,片段1主要是執(zhí)行的是JSBundle的加載過程。片段2主要是初始化組件,片段3主要是初始化組件配置表config,并將配置表注入到JSContext中。片段4主要是執(zhí)行js操作。那么如何實(shí)現(xiàn)加載過程的優(yōu)化呢?

實(shí)現(xiàn)方案二的理論猜想:

如果能有一種方式可以使React Native分步加載JSBundle并且不需要合并,那么就能減少1次合并操作與1次讀取complete.jsbundleI/O操作,理論上就可以有效的縮短頁面加載時(shí)間,事實(shí)證明這種方案也是可行的。因?yàn)镴SContext是由GlobalObject管理Java執(zhí)行的上下文,在同一個(gè)GlobalObject對(duì)應(yīng)的同一個(gè)JSContext中執(zhí)行Java代碼,執(zhí)行多個(gè)Java是沒有區(qū)別的,所以在同一個(gè)JSContext中分步加載common.jsbundle與bussiness.jsbundle效果應(yīng)該是一樣的。

JS 端如何實(shí)現(xiàn)的拆包

方案二JS端拆包的原理與步驟與方案一基本相同,相同的部分不再贅述。唯一不同的是需要對(duì)打包腳本需要進(jìn)行優(yōu)化,差異性具體如下:

1.通過react-native init指令創(chuàng)建新的空工程,使用wbrn-package工具生成common文件,具體使用指令如下:./pacakger bundle--entry-file ./core.js --bundle-output common.ios.bundle --bundle-encoding"utf-8" --platform “ios” --core-output common.json,使用該指令生成common.jsbundle文件以及對(duì)應(yīng)的common.json文件,common.json主要是記錄了RN原生組件以及唯一標(biāo)識(shí)符的映射關(guān)系。

2.如何獲取bussiness.jsbundle文件。通過wbrn-package工具根據(jù)不同的React Native頁面創(chuàng)建不同的、完整的complete.jsbundle文件,然后使用rn-package工具生成對(duì)應(yīng)bussiness文件,具體使用指令如下:./pacakger bundle --entry-file./index.js --bundle-output business.bundle --bundle-encoding "utf-8"--platform “ios" --core-file common.json。

3.通過熱更新平臺(tái)下發(fā)每個(gè)React Native頁面對(duì)應(yīng)的bussiness.jsbundle文件。

JS 端的JSBundle 是如何存儲(chǔ)Native 端的?

此步驟與方案一相同,不再贅述。

Native 端如何實(shí)現(xiàn)的合包

此方案中Native端采用的熱更新流程與邏輯與方案一基本相同,不同的是文件的合并方式以及jsbundle加載時(shí)機(jī),方案一采取的是文本文件的合并,而方案二是基于同一個(gè)JSContext分步加載common.jsbundle文件和bussiness.jsbundle文件的方式。具體流程如下圖13所示:

圖13 JBundle加載流程

與方案一差異的步驟如下:(已用紅框標(biāo)記)

1、將React Native本身框架提供的common.jsbundle文件提前在APP啟動(dòng)的時(shí)候加載JSGlobalContextRef中,目的是為了減少common加載的這部分時(shí)間。

2、根據(jù)bundleId從本地找到對(duì)應(yīng)的business.jsbundle文件,并將其加載到同一個(gè)JSContext環(huán)境中。

3、執(zhí)行JS代碼。

通過方案二能有效的減少jsbundle文件的讀取次數(shù)以及合并的時(shí)間,大大提高了頁面的加載速度。

實(shí)驗(yàn)過程中遇到了問題以及相應(yīng)的解決方案:

實(shí)驗(yàn)中我們發(fā)現(xiàn),如果按照上面思路依次進(jìn)入多個(gè)RN頁面,如果多個(gè)bussiness.jsbundle代碼完全不相同則可以正常展示,如果有相同的方法則會(huì)發(fā)生異常的錯(cuò)誤,那么如何處理多個(gè)RN頁面Bridge沖突?

我們使用的方案是維護(hù)一個(gè)基于common.jsbundle的Bridge池,每次創(chuàng)建新的頁面時(shí)就從Pool取出一個(gè)新的Bridge使用,取出之后在適當(dāng)?shù)臅r(shí)間再生成一個(gè)新的Bridge放入池中,使得Pool中始終有一個(gè)“干凈”的Bridge等待被使用,具體流程如下圖14、15所示:

圖14 Bridge沖突解決方案
圖15 方案二整體加載示意圖

那么改造的RN加載步驟:

1、APP啟動(dòng)之后從WBBridgePoolManager中讀取一個(gè)Common.jsbundle生成commonBridge,如果WBBridgePoolManager中不存在可用的commonBridge則直接生成。

2、在進(jìn)入對(duì)應(yīng)的具體的RN頁面后,根據(jù)跳轉(zhuǎn)協(xié)議中的bundleId則加載本地的對(duì)應(yīng)的bussniness.jsbundle文件,并將其放在commonBridge的同一個(gè)JSGlobalContextRef環(huán)境中去執(zhí)行。

3、根據(jù)此時(shí)bridge去創(chuàng)建RCTRootView,于此同時(shí)再次由common.jsbundle生成commonBridge放在WBBridgePoolManager隊(duì)列中進(jìn)行管理,以備下次使用。如果當(dāng)前的React Native需要進(jìn)行強(qiáng)制更新,則同樣從WBBridgePoolManager管理的pool中取出“干凈”Bridge去加載并創(chuàng)建新的RCTRootView,同時(shí)刪除舊的RCTRootView。

與方案一的數(shù)據(jù)對(duì)比:

相比方案一的3次本地讀取操作1次合并操作,方案二中僅僅進(jìn)行了2次本地讀取操作,大大降低了RN頁面的加載時(shí)間。

以iPhone7為例,方案二無緩存的情況下,加載時(shí)間為398ms,而方案一無緩存情況下加載時(shí)間為860ms,優(yōu)化比例為:53.72%. 方案二有緩存情況下,加載時(shí)間為140ms,而方案一有緩存情況下,加載時(shí)間為460ms,優(yōu)化比例為:69.6%

以iPhone5s為例,方案二無緩存的情況下,加載時(shí)間為830ms,而方案一無緩存情況下加載時(shí)間為1221ms,優(yōu)化比例為:32.02%. 方案二有緩存情況下,加載時(shí)間為400ms,而方案一有緩存情況下,加載時(shí)間為510ms,優(yōu)化比例為:21.56%.

以魅族X5為例,方案二無緩存的情況下,加載時(shí)間為410ms,而方案一無緩存情況下加載時(shí)間為957ms,優(yōu)化比例為:57.15%. 方案二有緩存情況下,加載時(shí)間為274ms,而方案一有緩存情況下,加載時(shí)間為578ms,優(yōu)化比例為:52.59%.

從上面數(shù)據(jù)可以看出在優(yōu)化效果十分明顯,iPhone高端機(jī)比低端機(jī)效果更顯著。

方案二仍存在的優(yōu)化空間:

截止到此58同城React Native的優(yōu)化暫且告一段落,但并不是說已經(jīng)不存在優(yōu)化的空間,試想下如果我們能否找到一種方案在App的生命周期中只創(chuàng)建一次JSContext運(yùn)行環(huán)境,每次進(jìn)入RN頁面只需要加載相應(yīng)的bussiness.jsbundle而不需要維護(hù)一個(gè)BridgePool,這樣能有效的減少App使用時(shí)占用的內(nèi)存大小。

總結(jié)

以上便是58同城React Native的優(yōu)化過程以及演進(jìn)的思路,項(xiàng)目的進(jìn)展始終按照“提出問題、分析問題、解決問題”的思路向前推進(jìn)。在研發(fā)過程中,結(jié)合公司自身的業(yè)務(wù)場(chǎng)景研發(fā)出相應(yīng)的打包平臺(tái)、熱更新平臺(tái)、調(diào)試工具以及詳細(xì)的接入文檔,形成了一套完善的React Native開發(fā)流程,為React Native在其他業(yè)務(wù)線能順利展開掃清障礙,減少各個(gè)業(yè)務(wù)線接入的溝通成本,提高工作效率。希望58 React Native的優(yōu)化過程,能給一些已經(jīng)應(yīng)用或者即將應(yīng)用React Native的開發(fā)者一些參考,也希望大家一起相互探討、學(xué)習(xí)。

58無線技術(shù)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容