CodePush熱更新組件詳細接入教程 什麼是CodePush CodePush是一個微軟開發的雲伺服器。通過它,開發者可以直接在用戶的設備上部署手機應用更新。CodePush相當於一個中心倉庫,開發者可以推送當前的更新(包括JS/HTML/CSS/IMAGE等)到CoduPush,然後應用將會查詢 ...
CodePush熱更新組件詳細接入教程
什麼是CodePush
CodePush是一個微軟開發的雲伺服器。通過它,開發者可以直接在用戶的設備上部署手機應用更新。CodePush相當於一個中心倉庫,開發者可以推送當前的更新(包括JS/HTML/CSS/IMAGE等)到CoduPush,然後應用將會查詢是否有更新。
接入流程
- 安裝 CodePush CLI
- 註冊 CodePush賬號
- 在CodePush伺服器註冊App
- RN代碼中集成CodePush
- 原生應用中配置CodePush
- 發佈更新的版本
CodePush 接入示例Demo地址:https://github.com/guangqiang-liu/CodePushDemo
1、安裝 CodePush CLI
安裝CodePush指令,直接在終端上輸入如下命令即可,註意:這個CodePush指令只需要全局安裝一次即可,如果第一次安裝成功了,那後面就不在需要安裝
$ npm install -g code-push-cli
image
2、註冊 CodePush賬號
註冊CodePush賬號也很簡單,同樣是只需簡單的執行下麵的命令,同樣這個註冊操作也是全局只需要註冊一次即可
$ code-push register
註意:當執行完上面的命令後,會自動打開一個授權網頁,讓你選擇使用哪種方式進行授權登錄,這裡我們統一就選擇使用GitHub即可
image
當註冊成功後,CodePush會給我們一個key
image
我們直接複製這個key,然後在終端中將這個key填寫進去即可,填寫key登錄成功顯示效果如下
image
我們使用下麵的命令來驗證我的登錄是否成功
$ code-push login
image
CodePush註冊登錄相關命令:
- code-push login 登陸
- code-push loout 註銷
- code-push access-key ls 列出登陸的token
- code-push access-key rm <accessKye> 刪除某個 access-key
3、在CodePush伺服器註冊App
為了讓CodePush伺服器有我們的App,我們需要CodePush註冊App,輸入下麵命令即可完成註冊,這裡需要註意如果我們的應用分為iOS和Android兩個平臺,這時我們需要分別註冊兩套key
應用添加成功後就會返回對應的production
和Staging
兩個key,production
代表生產版的熱更新部署,Staging
代表開發版的熱更新部署,在ios中將staging的部署key複製在info.plist的CodePushDeploymentKey值中,在android中複製在Application的getPackages的CodePush中
添加iOS平臺應用
$ code-push app add iOSRNHybrid ios react-native
image
添加Android平臺應用
$ code-push app add iOSRNHybridForAndroid Android react-native
image
我們可以輸入如下命令來查看我們剛剛添加的App
$ code-push app list
image
CodePush管理App的相關命令:
- code-push app add 在賬號裡面添加一個新的app
- code-push app remove 或者 rm 在賬號里移除一個app
- code-push app rename 重命名一個存在app
- code-push app list 或則 ls 列出賬號下麵的所有app
- code-push app transfer 把app的所有權轉移到另外一個賬號
4、RN代碼中集成CodePush
首先我們需要安裝CodeoPush組件,然後通過link命令添加原生依賴,最後在RN根組件中添加熱更新邏輯代碼
安裝組件
$ npm install react-native-code-push --save
image
添加原生依賴,這裡添加依賴我們使用自動添加依賴的方式
$ react-native link react-native-code-push
image
我們在RN項目的根組件中添加熱更新邏輯代碼如下
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View
} from 'react-native';
import CodePush from "react-native-code-push"; // 引入code-push
let codePushOptions = {
//設置檢查更新的頻率
//ON_APP_RESUME APP恢復到前臺的時候
//ON_APP_START APP開啟的時候
//MANUAL 手動檢查
checkFrequency : CodePush.CheckFrequency.ON_APP_RESUME
};
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' +
'Cmd+D or shake for dev menu',
android: 'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
type Props = {};
class App extends Component<Props> {
//如果有更新的提示
syncImmediate() {
CodePush.sync( {
//安裝模式
//ON_NEXT_RESUME 下次恢復到前臺時
//ON_NEXT_RESTART 下一次重啟時
//IMMEDIATE 馬上更新
installMode : CodePush.InstallMode.IMMEDIATE ,
//對話框
updateDialog : {
//是否顯示更新描述
appendReleaseDescription : true ,
//更新描述的首碼。 預設為"Description"
descriptionPrefix : "更新內容:" ,
//強制更新按鈕文字,預設為continue
mandatoryContinueButtonLabel : "立即更新" ,
//強制更新時的信息. 預設為"An update is available that must be installed."
mandatoryUpdateMessage : "必須更新後才能使用" ,
//非強制更新時,按鈕文字,預設為"ignore"
optionalIgnoreButtonLabel : '稍後' ,
//非強制更新時,確認按鈕文字. 預設為"Install"
optionalInstallButtonLabel : '後臺更新' ,
//非強制更新時,檢查到更新的消息文本
optionalUpdateMessage : '有新版本了,是否更新?' ,
//Alert視窗的標題
title : '更新提示'
} ,
} ,
);
}
componentWillMount() {
CodePush.disallowRestart();//禁止重啟
this.syncImmediate(); //開始檢查更新
}
componentDidMount() {
CodePush.allowRestart();//在載入完了,允許重啟
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit App.js
</Text>
<Text style={styles.instructions}>
{instructions}
</Text>
<Text style={styles.instructions}>
這是更新的版本
</Text>
</View>
);
}
}
// 這一行必須要寫
App = CodePush(codePushOptions)(App)
export default App
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
})
5、原生應用中配置CodePush
這裡原生應用中配置CodePush我們需要分別配置iOS平臺和Android平臺
配置iOS平臺
- 使用Xcode打開項目,Xcode的項目導航視圖中的PROJECT下選擇你的項目,選擇Info頁簽 ,在Configurations節點下單擊 + 按鈕 ,選擇Duplicate "Release Configaration,輸入Staging
image
- 選擇Build Settings tab,搜索Build Location -> Per-configuration Build Products Path -> Staging,將之前的值:
$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
改為:$(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME)
image
- 選擇Build Settings tab,點擊
+
號,選擇Add User-Defined Setting
,將key設置為CODEPUSH_KEY
,Release 和 Staging的值為前面創建的key,我們直接複製進去即可
image
- 打開Info.plist文件,在CodePushDeploymentKey中輸入
$(CODEPUSH_KEY)
,並修改Bundle versions為三位
image
iOS平臺CodePush環境集成完畢
配置Android平臺
6、發佈更新的版本
在使用之前需要考慮的是檢查更新時機,更新是否強制,更新是否要求即時等
更新時機
一般常見的應用內更新時機分為兩種,一種是打開App就檢查更新,一種是放在設置界面讓用戶主動檢查更新並安裝
-
打開APP就檢查更新
最為簡單的使用方式在React Natvie的根組件的componentDidMount方法中通過
codePush.sync()(需要先導入codePush包:import codePush from 'react-native-code-push')方法檢查並安裝更新,如果有更新包可供下載則會在重啟後生效。不過這種下載和安裝都是靜默的,即用戶不可見。如果需要用戶可見則需要額外的配置。具體可以參考codePush官方API文檔,部分代碼,完整代碼請參照文檔上面codePush.sync({ updateDialog: { appendReleaseDescription: true, descriptionPrefix:'\n\n更新內容:\n', title:'更新', mandatoryUpdateMessage:'', mandatoryContinueButtonLabel:'更新', }, mandatoryInstallMode:codePush.InstallMode.IMMEDIATE, deploymentKey: CODE_PUSH_PRODUCTION_KEY, });
上面的配置在檢查更新時會彈出提示對話框, mandatoryInstallMode表示強制更新,appendReleaseDescription表示在發佈更新時的描述會顯示到更新對話框上讓用戶可見
-
用戶點擊檢查更新按鈕
在用戶點擊檢查更新按鈕後進行檢查,如果有更新則彈出提示框讓用戶選擇是否更新,如果用戶點擊立即更新按鈕,則會進行安裝包的下載(實際上這時候應該顯示下載進度,這裡省略了)下載完成後會立即重啟並生效(也可配置稍後重啟),部分代碼如下
codePush.checkForUpdate(deploymentKey).then((update) => { if (!update) { Alert.alert("提示", "已是最新版本--", [ { text: "Ok", onPress: () => { console.log("點了OK"); } } ]); } else { codePush.sync({ deploymentKey: deploymentKey, updateDialog: { optionalIgnoreButtonLabel: '稍後', optionalInstallButtonLabel: '立即更新', optionalUpdateMessage: '有新版本了,是否更新?', title: '更新提示' }, installMode: codePush.InstallMode.IMMEDIATE, }, (status) => { switch (status) { case codePush.SyncStatus.DOWNLOADING_PACKAGE: console.log("DOWNLOADING_PACKAGE"); break; case codePush.SyncStatus.INSTALLING_UPDATE: console.log(" INSTALLING_UPDATE"); break; } }, (progress) => { console.log(progress.receivedBytes + " of " + progress.totalBytes + " received."); } ); } }
更新是否強制
如果是強制更新需要在發佈的時候指定,發佈命令中配置--m true
更新是否要求即時
在更新配置中通過指定installMode來決定安裝完成的重啟時機,亦即更新生效時機
- codePush.InstallMode.IMMEDIATE :安裝完成立即重啟更新
- codePush.InstallMode.ON_NEXT_RESTART :安裝完成後會在下次重啟後進行更新
- codePush.InstallMode.ON_NEXT_RESUME :安裝完成後會在應用進入後臺後重啟更新
如何發佈CodePush更新包
在將RN的bundle放到CodePush伺服器之前,我們需要先生成bundle,在將bundle上傳到CodePush
生成bundle
- 我們在RN項目根目錄下線創建bundle文件夾,再在bundle中創建創建ios和android文件夾,最後將生成的bundle文件和資源文件拖到我們的項目工程中
image
- 生成bundle命令
react-native bundle --platform 平臺 --entry-file 啟動文件 --bundle-output 打包js輸出文件 --assets-dest 資源輸出目錄 --dev 是否調試
$ react-native bundle --entry-file index.ios.js --bundle-output ./bundle/ios/main.jsbundle --platform ios --assets-dest ./bundle/ios --dev false
image
- 將生成的bundle文件和資源文件拖到我們的項目工程
image
上傳bundle
- 將生成的bundle文件上傳到CodePush,我們直接執行下麵的命令即可
$ code-push release-react <Appname> <Platform> --t <本更新包面向的舊版本號> --des <本次更新說明>
註意: CodePush預設是更新Staging 環境的,如果發佈生產環境的更新包,需要指定--d參數:--d Production,如果發佈的是強制更新包,需要加上 --m true強制更新
$ code-push release-react iOSRNHybrid ios --t 1.0.0 --dev false --d Production --des "這是第一個更新包" --m true
更新包上傳到CodePush伺服器成功後,效果圖如下:
image
查看發佈的歷史記錄,命令如下
查詢Production
$ code-push deployment history projectName Production
查詢Staging
$ code-push deployment history projectName Staging
image
對1.0.0版本的應用如何發佈第二個、第n個更新包
操作步驟和上面發佈第一個更新包流程一樣,我們任然先需要打出bundle包,將生成的bundle文件和資源文件拖到工程中,然後再將bundle發佈到CodePush
$ react-native bundle --entry-file index.ios.js --bundle-output ./bundle/ios/main.jsbundle --platform ios --assets-dest ./bundle/ios --dev false
$ code-push release-react iOSRNHybrid ios --t 1.0.0 --dev false --d Production --des "這是第二個更新包" --m true
註意事項
- 當我們在生成更新包之前,我們需要先將JS代碼打包成bundle,然後拖拽到項目中,打包之前我們需要先自己建立輸出bundle的文件夾
bundle -> ios
,打bundle命令如下:
$ react-native bundle --entry-file index.ios.js --bundle-output ./bundle/ios/main.jsbundle --platform ios --assets-dest ./bundle/ios --dev false
image
-
發佈更新包命令中的
-- t
對應的參數是和我們項目中的版本號一致的,這個不要誤理解為是更新包的版本號,例如項目中的版本號為1.0.0
, 這時如果我們需要對這個1.0.0
版本的項目進行第一次熱更新,那麼命令中的-- t
也為1.0.0
,第二次熱更新任然為1.0.0
-
項目的版本號需要改為三位的,預設是兩位的,但是CodePush需要三位數的版本號
-
發佈更新應用時,應用的名稱必須要和之前註冊過的應用名稱一致
image
- 創建應用時,信息要填寫正確
image
- 當執行link,命令卡住不執行時,這時直接按回車鍵先ignore key即可
image
- 還有最重要的一點需要註意的,就是打包證書環境要是良好的,證書不能報錯
福利時間
- 作者React Native開源項目OneM地址(按照企業開發標準搭建框架完成開發的):https://github.com/guangqiang-liu/OneM:歡迎小伙伴們 star
- 作者簡書主頁:包含50多篇RN開發相關的技術文章http://www.jianshu.com/u/023338566ca5歡迎小伙伴們:多多關註,多多點贊
- 作者React Native QQ技術交流群:620792950 歡迎小伙伴進群交流學習
- 友情提示:在開發中有遇到RN相關的技術問題,歡迎小伙伴加入交流群(620792950),在群里提問、互相交流學習。交流群也定期更新最新的RN學習資料給大家,謝謝大家支持!