平時使用React Native 時候, js代碼和圖片資源運行在一個Debug Server
上(需要cd 到RN目錄,然后終端執行 npm start 命令開啟本地服務 )。每次更新代碼之后只需要使用command+R
鍵刷新就可以看到代碼的更改,這種方式對於調試來說是非常方便的。
但是當我們需要發布App到App Store
的時候就需要打包,使用離線的js代碼和圖片。這就需要把JavaScript和圖片等資源打包成離線資源包,然后添加到Xcode項目中,最后一起打包發布到App Strore
中。
打包離線資源需要使用命令react-native bundle 。
React Native的 react-native bundle
命令是用來進行打包的命令,react-native bundle
的詳細命令選項https://github.com/facebook/react-native/blob/master/local-cli/bundle/bundleCommandLineArgs.js。
基礎知識:
其中我們常使用的一些命令選項如下:
-
--entry-file ,ios或者android入口的js名稱,比如index.js (有的項目根據具體的業務,命名根據業務命名,理論上可以隨便命名)
-
--platform ,平台名稱(ios或者android)
-
--dev ,設置為false的時候將會對JavaScript代碼進行優化處理。
-
--bundle-output, 生成的jsbundle文件的名稱,比如
./ios/bundle/index.ios.jsbundle (我們可以提前在當前目錄下創建ios/bundle系列文件夾。當然這個是根據需要隨意創建的)
-
--assets-dest 圖片以及其他資源存放的目錄,比如
./ios/bundle (道理同上)
打包命令如下:
react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ./iOS/bundle/index.jsbundle --assets-dest ./ios/bundle
補充:
npm 允許在package.json
文件里面,使用scripts
字段定義腳本命令。請參考
所以,為了方便使用,也可以把打包命令寫到npm script中:
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"bundle-ios":"node node_modules/react-native/local-cli/cli.js bundle --entry-file index.js --platform ios --dev false --bundle-output ./iOS/bundle/index.jsbundle --assets-dest ./ios/bundle"
},
然后運行命令直接打包:
npm run bundle-ios
實戰記錄:
1、接着上次在已有OC項目中引入RN的demo里面進行試驗。項目結構如下:
cd 到RN 目錄下
$ cd /Users/galahad/Desktop/ziliao/OC項目集成RN演練/yooweiRN/RNComponent
$ react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ./iOS/bundle/index.jsbundle --assets-dest ./ios/bundle
Loading dependency graph, done.
Loading dependency graph...bundle: Writing bundle output to: ./iOS/bundle/index.jsbundle
bundle: Done writing bundle output
我們發現已經生成了相關的離線包,如圖:
2、我們先刪掉相關的 index.jsbundle 離線包,然后用npm 腳本進項安裝試試:
$ cd /Users/galahad/Desktop/ziliao/OC項目集成RN演練/yooweiRN/RNComponent
$ npm run bundle-ios
> yooweiRN@0.0.1 bundle-ios /Users/galahad/Desktop/ziliao/OC項目集成RN演練/yooweiRN/RNComponent
> node node_modules/react-native/local-cli/cli.js bundle --entry-file index.js --platform ios --dev false --bundle-output ./iOS/bundle/index.jsbundle --assets-dest ./ios/bundle
Loading dependency graph, done.
Loading dependency graph...bundle: Writing bundle output to: ./iOS/bundle/index.jsbundle
bundle: Done writing bundle output
我們發現,同樣生成了我們想要的離線包
3、添加到OC項目中
用xcode 打開項目,Add Files to "yooweiRN"
選擇 iOS 文件夾,在option中選擇Create folder references ,注意不用選擇copy 的那個(省的又copy了一份,多余且不好管理),也可以根據實際情況進行調整。
然后目錄結構:
4、修改引用RN代碼
NSURL *jsCodeLocation;
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"iOS/bundle/index" withExtension:@"jsbundle"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"yooweiRN"
initialProperties:nil
launchOptions:nil];
//注意moduleName是RN 入口文件index.js 里面被注冊的appName。如: AppRegistry.registerComponent(appName, () => App);
具體appName是什么,看下引用文件里面是什么就可以了。
5、運行項目
離線包里的.jsbundle文件是經過優化處理的,因此運行效率也會比Debug的時候更高一些。
新增一些RN模塊:(修改了存放離線包的文件夾名稱)
中途發現如下錯誤:
1、如下圖,估計是語法有變化,現在找到對應的文件,將“逗號”去掉。
2、//#import "RCTRootView.h"//這樣引用的話,會報 Duplicate interface definition for class 'RCTRootView' 錯誤
3 、莫名其妙的出現下面的錯誤信息