《React-Native系列》40、 ReactNative之bundle檔案瘦身
【背景】
目前,我們的app中採用Native+RN的混合模式開發,每個由RN開發的頁面,頁面的載入都是載入的一個Bundle檔案,而一個Bundle檔案的大小為500-600Kb。
在沒有內建bundle檔案的情況下,使用者想要使用所有由RN開發的功能,需要下載 n* 500 kb的檔案。
在有內建bundle檔案的情況下,如果一個頁面有更新,那麼使用者至少需要下載500kb的檔案。
在移動端,頻繁的需要去下載500kb大小的檔案,是無法被接受的。
【目的】
1、控制bundle資源包的大小,為內建安裝包瘦身
2、減小頁面更新bundle檔案大小,減少App端下載bundle的流量
【詳細設計】
1)google-diff-match-patch簡介:
要對文字檔案的進行比較的時候,可以考慮使用google-diff-match-patch,它可以對文字檔案進行比較、匹配和生成補丁的操作。
2)bundle檔案拆分方案:
commonPart.bundle生成的方法如下:(android 和 iOS的commonPart 需要分開生成)
curl 'http://localhost:8081/blank.ios.bundle?minify=true&dev=false' -o common.ios.bundle
其中blank.ios.js 檔案內容如下:
import React, { Component } from 'react'; import {} from 'react-native';
拆分完成後的bundle示意圖如下:
3)bundle檔案diff和patch流程
【資源打包】
提供一個shell,可以支援bundle檔案的diff,生成patch檔案,並對其zip壓縮。
使用效果如下:
【效果】
可以看到,bundle檔案由560kb 縮小到了15kb。
綜合以上,就達到了bundle檔案瘦身的目的。
以下更新於20170328
【現象】
安卓端2.0.1版本升級安裝到2.1.0後,app啟動,長時間白屏,導致ANR。選擇等待,重新進入app,白屏消失,恢復正常。
【分析】
1、從bugly後臺可以看到導致ANR的堆疊,從堆疊可以看出,錯誤出現在:
Object[] results = diff_match_patch.patch_apply(patches, commonStr);
此段程式碼的作用是:google-diff-match-patch 合併差異描述檔案,生成業務完整bundle檔案。
2、耗時分析
在app啟動的時候,會在主執行緒中初始化RNSDK,執行initRnManager方法,初次使用時會unZip bundle描述檔案, 執行 diffExecute 方法, 生成業務完整bundle,當業務bundle都生成完畢後,會進入app首頁。
分析 diffExecute 方法執行時間,發現在不同的Android機型下,合併一個bundle檔案耗時時間在 100 - 3500 ms不等。目前共4個bundle檔案,最長耗時達到13000 ms,因此導致啟動app時ANR。
在Android平臺下,出現這種耗時差異,主要是由於Android裝置效能差異較大,對大檔案的diff操作有不同的響應時間。
在iOS平臺下,由於iOS系統性能好,不存在此問題。
【解決方案】
將內建差異描述檔案改為內建完整bundle檔案
使用者初次使用app時,只需要將asset裡內建的業務bundle 拷貝到 data/data/com.xxx.xxx/app_bundle/時間戳/ 目錄,去掉match-patch 流程。這樣app啟動時可以直接使用內建的完整bundle檔案。
備註:
1、對內建檔案的處理只發生在使用者初次使用app、版本覆蓋安裝、使用者通過系統或第三方工具手動清除app對應的資原始檔。
2、增量更新功能,還是使用差異描述檔案的方式下發,但是執行是在一個BundleTask 非同步任務中,在後臺執行,不影響主執行緒。