開(kāi)發(fā)環(huán)境
- macOS High Sierra 10.13.5
- react-native-cli: 2.0.1
- react-native: 0.55.4
- android studio: 3.1.3
- Xcode: 9.4.1 (9F2000)
先說(shuō)背景
最近的項(xiàng)目要使用 React Native 進(jìn)行開(kāi)發(fā)驳癌,并且實(shí)現(xiàn)熱更新功能葫松,React Native 默認(rèn)打包策略是將 bundle 文件及相關(guān)資源文件放置在項(xiàng)目中固定位置 ,該位置在運(yùn)行時(shí)無(wú)法進(jìn)行更改漾岳,要實(shí)現(xiàn)熱更新需要有兩個(gè)步驟:
- 下載熱更新的 bundle 及圖片資源文件并放置到指定的應(yīng)用的可寫目錄
- 啟動(dòng)時(shí)加載指定目錄下的 bundle 文件
本文討論的主要內(nèi)容為第 2 點(diǎn)狸臣,如何讓 React Native 應(yīng)用啟動(dòng)時(shí)加載指定目錄下的 bundle 文件莹桅。
再說(shuō)干貨
1. 打包說(shuō)明
打包使用 react-native bundle 命令進(jìn)行打包,android 和 iOS 平臺(tái)需要分別進(jìn)行打包烛亦,因?yàn)榇虬鰜?lái)的 bundle 文件及圖片資源文件內(nèi)容及格式有差別诈泼。
-
android 打包命令
# 切換項(xiàng)目根目錄,我本機(jī)為 ~/Documents/RNSample
cd ~/Documents/RNSample
# 有無(wú)相關(guān)目錄煤禽,則執(zhí)行創(chuàng)建文件保存目錄
mkdir -p bundles/android/bundles
# 執(zhí)行打包命令
react-native bundle --entry-file index.js --platform android --dev false --bundle-output ./bundles/android/bundles/index.android.bundle --assets-dest ./bundles/android/bundles
打包命令執(zhí)行成功后铐达,bundles/android/bundles
目錄中會(huì)生成如下內(nèi)容
-
iOS 打包命令
# 切換項(xiàng)目根目錄,我本機(jī)為 ~/Documents/RNSample
cd ~/Documents/RNSample
# 有無(wú)相關(guān)目錄檬果,則執(zhí)行創(chuàng)建文件保存目錄
mkdir -p bundles/ios/bundles
# 執(zhí)行打包命令
react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ./bundles/ios/bundles/index.ios.bundle --assets-dest ./bundles/ios/bundles
打包命令執(zhí)行成功后瓮孙,bundles/ios/bundles
目錄中會(huì)生成如下內(nèi)容
打包命令參數(shù)說(shuō)明
# 程序入口js文件
--entry-file
# 打包平臺(tái)類型,取值 android , ios
--platform
# 是否為開(kāi)發(fā)模式选脊,默認(rèn)為 true ,打包時(shí)需要設(shè)置成 false
--dev
# js bundle 文件輸出路徑
--bundle-output
# 圖片資源輸出目錄
--assets-dest
以上打包成功的文件夾備用杭抠,后續(xù)需要將子目錄 bundles 復(fù)制到模擬器或者設(shè)備上的指定目錄中,以便 React Native 項(xiàng)目加載使用恳啥。
2. 代碼調(diào)整
-
android 處理方案
關(guān)鍵代碼為偏灿,重寫 ReacNativeHost 的 getJSBundleFile 方法,本例設(shè)置從SD卡根目錄/bundles/index.android.bundle
加載文件
/**
* 重寫該方法钝的,以改變 JSBundleFile 的加載路徑
* @return
*/
@Nullable
@Override
protected String getJSBundleFile() {
// 設(shè)置從 SD卡根目錄/bundles/index.android.bundle 加載文件
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "bundles/index.android.bundle";
Log.i("RN", path);
return path;
}
-
iOS 處理方案
關(guān)鍵代碼為翁垂,重寫使用react-native-cli 生成 iOS 項(xiàng)目中的 AppDelegate 類的 didFinishLaunchingWithOptions 方法中獲取 bundle 路徑的代碼,本例設(shè)置從沙盒根目錄/bundles/index.ios.bundle
加載文件
NSURL *jsCodeLocation;
// 獲取應(yīng)用沙盒根目錄
NSString * jsBundlePath = NSHomeDirectory();
NSLog(@"sanbox root path = %@",jsBundlePath);
// 調(diào)整過(guò)的加載路徑硝桩,設(shè)置從 沙盒根目錄/bundles/index.ios.bundle 加載文件
jsCodeLocation = [NSURL URLWithString:[jsBundlePath stringByAppendingString:@"/bundles/index.ios.bundle"]];
NSLog(@"new jsCodeLocation= %@",jsCodeLocation);
3. 相關(guān)文件放置說(shuō)明
-
android
將 index.android.bundle 文件及打包出的相關(guān)資源文件夾放置在SD卡根目錄的 bundles 文件夾下沮峡。
-
iOS
將 index.ios.bundle 文件及打包出的相關(guān)資源文件夾放置在沙盒根目錄的 bundles 文件夾下。