ReactNative 的熱更新主流的有ReactNative中文網(wǎng)的pushy和微軟的CodePush吏祸,經(jīng)過對比我選了CodePush意乓。這里CodePush是用的微軟的官方服務(wù),也可以用CodePush自行搭建服務(wù)呻惕。
CodePush 安裝與注冊
1.安裝 CodePush CLI
使用命令npm install -g code-push-cli
安裝CodePush終端
ps.都在開發(fā)React Native了礁哄,npm安裝就無需贅言了吧映琳。
2.注冊CodePush 賬號
CodePush終端安裝完成后就可以使用code-push命令了浅侨。
在終端輸入code-push register
纽谒,會跳轉(zhuǎn)授權(quán)網(wǎng)頁。在這個網(wǎng)頁可以選擇Github.
授權(quán)完成后如输,CodePush會顯示你的Access Key鼓黔,復(fù)制輸入到終端即可完成注冊并登陸。
ps.只要不主動退出(通過code-push logout
命令)不见,登陸狀態(tài)會一直有效请祖。
在CodePush服務(wù)器中創(chuàng)建App
在終端輸入code-push app add <appName> <os> <platform>
即可完成創(chuàng)建,注冊完成之后會返回一套deployment key脖祈,包括Staging和Production。該key在后面步驟中會用到刷晋。
因為發(fā)布的時候使用的打包命令是有所不同的盖高,因此需要做區(qū)分。
code-push相關(guān)常見命令如下:
Usage: code-push app <command>
命令:
add 創(chuàng)建一個新的App
remove 刪除App
rm 刪除App
rename 重命名已經(jīng)存在App
list 列出與你賬戶關(guān)聯(lián)的所有App
ls 列出與你賬戶關(guān)聯(lián)的所有App
transfer 將一個App的所有權(quán)轉(zhuǎn)讓給另一個帳戶
CodePush集成
這里只講iOS集成
1.在React Native項目中安裝codePush依賴:npm install --save react-native-code-push
2.打開 Info.plist文件眼虱,在CodePushDeploymentKey
中輸入deployment key喻奥,并修改Bundle versions為三位,如下圖
ps1:可以通過 code-push app ls
查看所有已添加app
ps2:可以通過code-push deployment ls JWDemo-OC-RN -k
查看deployment key)
3.在OC項目中導(dǎo)入CodePush庫捏悬,如下圖:(CodePush需要指定podspec指向本地文件路徑)
4.設(shè)置bundle路徑:
#import <CodePush/CodePush.h>
// NSURL *jsCodeLocation = [NSURL
// URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];
NSURL *jsCodeLocation = [CodePush bundleURL];
RCTRootView *rootView =
[[RCTRootView alloc] initWithBundleURL : jsCodeLocation
moduleName : @"MyReactNativeApp"
initialProperties : nil
launchOptions : nil];
UIViewController *vc = [[UIViewController alloc] init];
vc.view = rootView;
VC = vc;
ps:需要注意的是CodePush的bundleURL中的bundle名字為main
撞蚕,所以需要將打出來的包名命名為main.jsbundle
遇到的坑:
使用[CodePush bundleURL]
讀取bundle路徑時,首次打iOS原生包時过牙,需要將bundle包打入項目內(nèi)甥厦,
使用命令react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ../Mars/bundle/main.jsbundle --assets-dest ../Mars/bundle
將bundle包及資源文件打包,然后拖入原生項目中寇钉。特別注意:bundle文件夾及里面的main.jsbundle和main.jsbundle.meta 文件拖入是要選
然后移除assets文件夾對于項目的依賴刀疙,再將assets拖入工程如下圖選擇:
最終效果如下,assets文件夾應(yīng)該是藍色的:
如果不這樣做的話扫倡,首次運行會導(dǎo)致讀取不到資源文件或者bundle
使用react-native-code-psuh進行熱更新
該配置的都已經(jīng)配置完了谦秧,接下來就是使用了。
在使用之前需要考慮的是檢查更新時機,更新是否強制疚鲤,更新是否要求即時等等锥累。
更新時機
一般常見的應(yīng)用內(nèi)更新時機分為兩種,一種是打開APP就檢查更新集歇,一種是放在設(shè)置界面讓用戶主動檢查更新并安裝桶略。
打開APP就檢查更新
最為簡單的使用方式在React Natvie的根組件的componentDidMount方法中通過
codePush.sync()(需要先導(dǎo)入codePush包:import codePush from 'react-native-code-push')方法檢查并安裝更新,如果有更新包可供下載則會在重啟后生效鬼悠。不過這種下載和安裝都是靜默的删性,即用戶不可見。如果需要用戶可見則需要額外的配置焕窝。具體可以參考codePush官方API文檔蹬挺,下面是個人的一些實踐過的配置:
codePush.sync({
updateDialog: {
appendReleaseDescription: true,
descriptionPrefix:'\n\n更新內(nèi)容:\n',
title:'更新',
mandatoryUpdateMessage:'',
mandatoryContinueButtonLabel:'更新',
},
mandatoryInstallMode:codePush.InstallMode.IMMEDIATE,
//deploymentKey: CODE_PUSH_PRODUCTION_KEY,//(若在原生項目中Info.plist設(shè)置了CodePushDeploymentKey則不需要在這里設(shè)置deploymentKey)
});
上面的配置在檢查更新時會彈出提示對話框, mandatoryxxx表示強制更新它掂,appendReleaseDescription表示在發(fā)布更新時的描述會顯示到更新對話框上讓用戶可見
更新是否強制
如果是強制更新需要在發(fā)布的時候指定巴帮,發(fā)布命令中配置--m true,下文在細說
更新是否要求即時
在更新配置中通過指定installMode來決定安裝完成的重啟時機虐秋,亦即更新生效時機
codePush.InstallMode.IMMEDIATE:表示安裝完成立即重啟更新
codePush.InstallMode.ON_NEXT_RESTART:表示安裝完成后會在下次重啟后進行更新
codePush.InstallMode.ON_NEXT_RESUME:表示安裝完成后會在應(yīng)用進入后臺后重啟更新
發(fā)布codepush更新包
codepush的更新包發(fā)布其實很簡單榕茧。在終端輸入命令
code-push release-react <appName> <platform> [options]
CodePush默認(rèn)是更新 Staging 環(huán)境的,如果發(fā)布生產(chǎn)環(huán)境的更新包客给,需要指定--d參數(shù):--d Production 用押,如果發(fā)布的是強制更新包,需要加上 --m true強制更新
示例:
code-push release-react Demo-RN-OC ios --t 3.0.1 --dev false --d Staging --des “測試文案”
選項:
Usage: code-push release-react <appName> <platform> [options]
--bundleName, -b Name of the generated JS bundle file. If unspecified, the standard bundle name will be used, depending on the specified platform: "main.jsbundle" (iOS), "index.android.bundle" (Android) or "index.windows.bundle" (Windows) [字符串] [默認(rèn)值: null]
--deploymentName, -d Deployment to release the update to [字符串] [默認(rèn)值: "Staging"]
--description, --des Description of the changes made to the app with this release [字符串] [默認(rèn)值: null]
--development, --dev Specifies whether to generate a dev or release build [布爾] [默認(rèn)值: false]
--disabled, -x Specifies whether this release should be immediately downloadable [布爾] [默認(rèn)值: false]
--entryFile, -e Path to the app's entry Javascript file. If omitted, "index.<platform>.js" and then "index.js" will be used (if they exist) [字符串] [默認(rèn)值: null]
--gradleFile, -g Path to the gradle file which specifies the binary version you want to target this release at (android only). [默認(rèn)值: null]
--mandatory, -m Specifies whether this release should be considered mandatory [布爾] [默認(rèn)值: false]
--noDuplicateReleaseError When this flag is set, releasing a package that is identical to the latest release will produce a warning instead of an error [布爾] [默認(rèn)值: false]
--plistFile, -p Path to the plist file which specifies the binary version you want to target this release at (iOS only). [默認(rèn)值: null]
--plistFilePrefix, --pre Prefix to append to the file name when attempting to find your app's Info.plist file (iOS only). [默認(rèn)值: null]
--rollout, -r Percentage of users this release should be immediately available to [字符串] [默認(rèn)值: "100%"]
--privateKeyPath, -k Specifies the location of a RSA private key to sign the release with [字符串] [默認(rèn)值: false]
--sourcemapOutput, -s Path to where the sourcemap for the resulting bundle should be written. If omitted, a sourcemap will not be generated. [字符串] [默認(rèn)值: null]
--targetBinaryVersion, -t Semver expression that specifies the binary app version(s) this release is targeting (e.g. 1.1.0, ~1.2.3). If omitted, the release will target the exact version specified in the "Info.plist" (iOS), "build.gradle" (Android) or "Package.appxmanifest" (Windows) files. [字符串] [默認(rèn)值: null]
--outputDir, -o Path to where the bundle and sourcemap should be written. If omitted, a bundle and sourcemap will not be written. [字符串] [默認(rèn)值: null]
--config, -c Path to the React Native CLI configuration file [字符串] [默認(rèn)值: null]
-v, --version 顯示版本號 [布爾]
常用部署命令如下:
Usage: code-push deployment <command>
命令:
add 在已存在的App中創(chuàng)建一個部署
clear 清除與部署相關(guān)的發(fā)布歷史記錄
remove 在App中刪除一個部署
rm 在App中刪除一個部署
rename 重命名一個已存在的部署
list 列出App中的所有部署
ls 列出App中的所有部署
history 列出一個部署的發(fā)布歷史記錄
h 列出一個部署的發(fā)布歷史記錄
至此靶剑,一個完整的發(fā)布蜻拨,檢查,安裝流程已經(jīng)基本描述完了桩引。調(diào)用RN上的熱更新代碼應(yīng)該就能收到更新提醒缎讼。