每當在模擬器上完成了開發,都想到真機上試試,正好前段時候淘了一個imac。
這裏就以打包rndemo到iphone爲例,講一下react ntive ios打包到真機的流程。
一、前置
1.有個iphone加個mac
2.首先react native的環境要正確安裝,還未完成這一步的,請到react native官網或中文站查看具體流程
3.xcode等環境安裝完畢
4.rn應用能在模擬器中跑起來,至少不要有什麼致命報錯吧
二、生成jsbundle
1.進入rn項目的ios工程文件夾,找到和rn項目同名的文件夾,打開AppDelegate.m文件,將這一行註釋掉(爲了方便真機和模擬器間的切換,儘量註釋):
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
新加一行:
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"index.ios" withExtension:@"jsbundle"];
如果需要切換回模擬器調試,只需要將新加這行註釋掉,並恢復原代碼即可。
新加這行代碼大概意思就是告訴native rn代碼的入口,我們會在下一步生成這個jsbundle。
2.打開終端,進入你的rn工程,在根目錄下執行bundle命令:
react-native bundle --entry-file ./index.ios.js --bundle-output ./ios/bundle/index.ios.jsbundle --platform ios --assets-dest ./ios/bundle --dev false
參數說明:
--entry-file 指定入口文件 因爲要打包ios平臺,所以指定爲rn項目的index.ios.js作爲入口
--bundle-output 指定輸出的jsbundle文件路徑和文件名 指定到rn項目的ios工程文件夾下,記得一定要先創建bundle文件夾,不然終端會報文件夾找不到的錯誤
--platform 指定平臺類型
--assets-dest 指定資源文件夾路徑 assets文件夾的路徑,包含圖片、node模塊等資源
--dev 是否爲開發模式 如果設置爲false,不會產生警告,並且bundle會被壓縮
還有其他命令,比如:transformer、prepack、bundle-encoding等,可以到官網查看具體介紹。
bundle生成完成後,終端會有類似提示:
3.用xcode Open another project打開rn項目的ios工程文件夾:
將之前打包好的jsbundle和assets拖入rndemo這個文件夾下面,注意一定要選擇 Create folder references:
三、配置網絡訪問白名單
應用中如果有網絡請求,這一步必不可少,要不然會出現網絡請求失敗的錯誤提示。
1.打開Info.plist:
2.在App Transport Security Settings下添加key:Exception Domains,類型爲Dictionary。
3.在Exception Domains下添加你的應用可能會訪問到的域名,key爲域名,類型爲Dictionary。需要注意的是:
iOS 9及以上版本,非HTTS的網絡是被禁止的,當然我們也可以把NSAllowsArbitraryLoads設置爲YES禁用ATS。不過iOS 10從2017年1月1日起蘋果不允許我們通過這個方法跳過ATS,也就是說強制我們用HTTPS,如果不這樣的話提交App可能會被拒絕。但是我們可以通過NSExceptionDomains來針對特定的域名開放HTTP可以容易通過審覈。每個域名都需要三個屬性,key分別爲:
NSIncludesSubdomains 是否包含子域 設置爲true
NSExceptionRequiresForwardSecrecy 指定域名是否支持Forward Secrecy 設置爲false
NSExceptionAllowsInsecureHTTPLoads 是否能使用http協議,默認是隻能請求https的 設置爲true
類型都爲Boolean。
比如這裏,我增加了api.douban.com這個白名單域,因爲它本身就是走的https協議,那三個子屬性我便沒再做配置。應用需要訪問的域都可以加到這裏。
如果進入應用以後,依然無法請求網絡,請檢查 通用->蜂窩移動網絡->使用無線局域網與蜂窩移動的應用->你的應用 設置允許的數據使用。
四、設置應用圖標和閃屏圖片(啓動圖)
在xcode中點擊Images.xcassets文件夾,這是保存應用圖標和閃屏等的文件夾:
可以看到應用圖標是按照尺寸分類了的,具體每個類型的圖片大小要求可以自行查找資料,一定要保證同樣的分辨率,而且不需要是圓角,否則在編譯的時候會有警告提示。
閃屏的話,可以右鍵添加LaunchImage,也是同樣的按尺寸和方向分類的,只需要拖入對應的圖片即可。
圖標和啓動圖我都是胡亂弄的,要弄齊所有還是很麻煩。
五、連接iphone到電腦,並讓它們處於wifi的同一網段
1.連接好iphone以後,將設備選擇爲你的iphone,並點擊xcode左上方的build按鈕,就可以執行構建了:
2.構建完成以後,xcode會有個沒法啓動應用的提示。原因是你的手機沒有信任這個程序,在手機設置中:通用->設備管理->開發者應用 中信任這個應用,然後點擊應用圖標即可啓動應用了。
構建中途可能會有錯誤或者警告提示,可根據具體的提示查找解決辦法。
我遇到過兩個錯誤:
1.app id不唯一,在這裏可以重新設置:
2.簽名那裏沒有指定一個team:
在這裏可以按照提示一步一步設置
還需要注意的是部署的目標要和iphone系統版本一致:
對於native小白來說,這些的確很陌生,哈哈
六、簡化bundle命令
react-native的bundle子命令有太多的參數需要設置,但是我們每次打包新bundle並需要改變什麼,至少大多數情況是這樣的。觀察raect-native的node_modules依賴,發現已經安裝了yargs和shelljs,這是其他包間接依賴的。這兩個模塊可以幫助我們創建自己的bundle命令行工具。以前正好看過這兩個包的介紹,這裏正好用上。
簡短介紹:
yargs 可以幫助我們分析和整理命令的參數,比直接操作process.argv數組要方便得多,定製性也很強。
shelljs 提供了調用shell命令的能力,能夠在js中書寫shell腳本,是對child_process的擴展。
命令行製作步驟:
1.創建命令行文件
我們在rn項目的根目錄創建一個mkbundle.js的文件,文件開頭加上 #!/usr/bin/env node ,指定使用node來執行這個文件,注:這僅僅是類unix系統的方式,windows系統請使用bat來啓動,或者使用powershell來執行,這需要win7以上支持。
2.修改package.json文件
加入一個bin屬性,值爲一個對象
"bin": { "mkbundle": "./mkbundle.js" },
3.執行 npm link 命令
完成以後,在rn項目的根目錄,mkbundle就成爲了一個在終端裏可執行的全局命令,關於link命令,這裏有篇不錯的文章
4.測試
在mkbundle.js中加入一行測試代碼 console.log(123); ,並執行 mkbundle 命令,
可以看見123被輸出出來了,配置到這裏就成功了。下面是命令行工具的實現:
5.實現這個工具
1 #!/usr/bin/env node 2 3 /** 4 * '$ mkbundle' 5 * 用途:簡化jsbundle打包命令 6 * 作者:james 7 * 依賴:yargs、shelljs兩個包。rn項目默認會有包依賴這兩個包,在項目初始化完畢並執行‘npm install’後,不需要再手動安裝 8 * 使用:進入終端,切換目錄至rn項目的根目錄,即本js文件所在目錄,執行mkbundle命令即可 9 * 說明:本命令行工具代理了react-native命令下的bundle子命令的5個最常用參數,這5個參數均已設置默認值,都可以不傳,也可以只傳某些需要改變的值 10 * 11 * bundle子命令的所有參數: 12 * 13 * --entry-file 指定js入口文件的路徑 [已代理,簡寫爲 -ef] 14 * --platform 指定設備平臺類型 [已代理,簡寫爲 -p] 15 * --transformer 指定一個自定義的轉換器 16 * --dev 如果爲否,將關閉警告並壓縮bundle文件 [已代理] 17 * --prepack 如果爲真,將輸出預打包格式的bundle 18 * --bridge-config 指定bridge json配置文件的名稱 19 * --bundle-output 指定bundle文件的輸出路徑 [已代理,簡寫爲 -bo] 20 * --bundle-encoding 指定bundle文件的編碼格式 21 * --sourcemap-output 指定soucemap的文件名稱及路徑 22 * --assets-dest 指定資源文件夾的輸出目錄 [已代理,簡寫爲 -ad] 23 * --verbose 如果爲真,將記錄日誌 24 */ 25 26 require('shelljs/global'); 27 28 if (!which('react-native')){ 29 echo('請先安裝react-native-cli'); 30 exit(1); 31 } 32 33 const {ef, bo, ad, p, dev} = require('yargs') 34 .option('entry-file', { 35 alias: 'ef', 36 demand: false, 37 default: './index.ios.js', 38 describe: '指定js入口文件的路徑', 39 type: 'string' 40 }) 41 .option('bundle-output', { 42 alias: 'bo', 43 demand: false, 44 default: './ios/bundle/index.ios.jsbundle', 45 describe: '指定bundle文件的輸出路徑', 46 type: 'string' 47 }) 48 .option('assets-dest', { 49 alias: 'ad', 50 demand: false, 51 default: './ios/bundle', 52 describe: '指定資源文件夾的輸出目錄', 53 type: 'string' 54 }) 55 .option('platform', { 56 alias: 'p', 57 demand: false, 58 default: 'ios', 59 describe: '指定設備平臺類型', 60 type: 'string' 61 }) 62 .option('dev', { 63 alias: 'dev', 64 demand: false, 65 default: false, 66 describe: '如果爲否,將關閉警告並壓縮bundle文件', 67 boolean: true, 68 type: 'boolean' 69 }) 70 .help('help') 71 .alias('help', 'h') 72 .argv; 73 74 rm('-rf', './ios/bundle'); 75 mkdir('-p', './ios/bundle'); 76 77 if (exec(`react-native bundle --entry-file ${ef} --bundle-output ${bo} --assets-dest ${ad} --platform ${p} --dev ${dev}`).code != 0){ 78 echo('錯誤:bundle 失敗'); 79 exit(1); 80 }
可以看到,我把bundle命令最常用的5個參數做了代理,並設置了別名來簡化輸入。執行 mkbundle 命令的時候,甚至可以什麼參數都不輸入,因爲它們都指定了默認的值。如果某些參數值需要修改,只需單獨設置這些參數的值即可。
參數的默認值可以根據自身項目情況和Appdelegate.m的配置來設置。
這個工具目前只是一個雛形,可以根據我們的需要進行擴展,畢竟yargs和shelljs的配合提供了很強大的功能。
執行 mkbundle --h 命令,可以看到幫助信息,如果你有合作的夥伴或者某一天會publish這個工具,這對使用者會有幫助:
執行 mkbundle 命令,和我們手動輸入 react-native bundle --xxx xx --xxx -xx ... 的結果是一樣的,路徑以及文件都被正確的創建出來了:
快去構建你的APP吧