React Native熱更新(CodePush使用)
在移動應用開發過程中,應用的發布上線一直是個耗時且長時間沒有很好解決的問題。特別是對于蘋果開發者,受蘋果的生態環境影響每次審核時間一到7天不等。筆者記得15年曾有新應用上線多次被拒,從提交審核到正式上線前前后后磨蹭了半個多月才真正發布成功。安卓的相對就不會產生那么多不愉快,審核時間半天左右。今天筆者想向大家分享的是跨平臺開發中的CodePush使用,CodePush的出現有效的解決了React Native 應用在動態更新方面耗時過長問題。
由于js本身具備動態加載特性,RN的熱更新并不像原生那么復雜,RN的熱更新更像是原生版本的熱更新,流程大致如下:
RN在啟動過程中將一系列的資源包打包成jsbundle文件,系統加載jsbundle文件來解析渲染界面。
? ? 1.CodePush簡介
CodePush是微軟開發的云服務器。通過它開發者可以直接在用戶的設備上部署手機應用更新。CodePush 作為一個中央倉庫,開發者可以推送更新 (JS, HTML, CSS and images),應用可以從客戶端 SDK 里面查詢更新。CodePush 可以讓應用有更多的可確定性,也可以讓你直接接觸用戶群。在修復一些小問題和添加新特性的時候,不需要經過二進制打包,可以直接推送代碼進行實時更新。
? ? 2.CodePush優勢
CodePush可以實時推送代碼的更新、直接對用戶部署代碼更新、支持React Native和Cordova、支持JavaScript文件與圖片資源的更新、管理Alpha,Beta和生產環境應用。
? ? 3.CodePush安裝
????????a.安裝CodePush CLI,通過NodeJS-based CLI管理CodePush賬號。
????????????1.打開蘋果電腦終端,輸入sudonpm install -g code-push-cli;
????????????2.驗證是否安裝成功,輸入code-push -v查看版本。
? ? ? ? ?b.創建codePush賬號
????????????1.在終端輸入code-push register,進入網頁注冊頁面,注冊成功后得到.
得到的這個值就是你終端里需要輸入的token;
?????????????2.在終端輸入得到的token,成功后得到如下反饋;
?????????????3.在終端輸入code-push app add (應用名稱);
?? ? ? ? ????code-push相關命令:
? ? ? ? ? ? ? code-push app下相關命令
完成上述操作后,你的應用已經注冊到codepush服務端。
????????????4.終端中輸入code-push deployment ls (應用名稱)-k,查看對應的Deployment Key;
? ? ? ? ? ? ?5.終端輸入code-push access-key ls;(創建時間和名字)
? ? 4.集成CodePush SDK
????????1.iOS集成,CodePush官方提供RNPM、CocoaPods與手動三種在iOS項目中集成CodePush的方式。
????????????a.React Native項目中安裝codePush依賴,終端輸入:npm i react-native-code-push --save
????????????b.react-native和react-native-code-push的構建關聯,終端輸入:react-native link react-native-code-push,link的主要作用是進行庫文件依賴關系關聯。如果react-native link操作成功,在iOS和Android工程中均能看到相應的依賴(具體表現為打開Xcode,可以在【Build Phases】→【Link Binary With Libraries】依賴庫看到對應.a文件;在Android項目app目錄中build.gradle文件下的dependencies中看到依賴庫)。可以選擇輸入對應的deployment key或者直接跳過,筆者選擇輸入對應發deployment key,RN項目中安卓跟iOS都需要。
????????????c.Xcode中的配置(手動連接)
????????????1.引入CodePush.xcodeproj,相同的方法只是你需要的CodePush.xcodeproj,三方項目的實現,工程依賴。
????????????2.引入CodePush SDK、libz.tbd,
????????????3.添加code-push頭文件檢索
????????4.配置deployment key
? ? ? ? 在react-native link react-native-code-push環節我們跳過了deployment key在Xcode端的配置,在這里我們需要手動配置。
????????????a.在Xcode的項目導航視圖中的PROJECT下選擇你的項目,選擇Info頁簽,在Configurations節點下單擊+按鈕,選擇Duplicate“Release Configaration,輸入Staging。
????????????b.在build Settings頁簽中單擊+按鈕然后選擇Add User-Defined Setting,然后輸入CODEPUSH_KEY,然后填入deployment key。
新增的CODEPUSH_KEY節點下Debug不用填,Release填入的是CodePush上Production的key值,Staging填入的是CodePush上Staging的key值:
????????????c.打開Info.plist文件,在CodePushDeploymentKey中輸入$(CODEPUSH_KEY),并修改Bundle versions為三位,如圖:
至此,ios原生層的CodePush集成已經完成,接下來在React-native使用接入CodePush。
?????????2.安卓集成
? ????????????a.在項目中安裝react-native-code-push插件,終端輸入:npm install --save react-native-code-push;(如果你在項目中iOS已經集成可以省略)
????????????? b.在Android project中安裝插件,CodePush提供了兩種方式:RNPM和Manual。筆者使用RNPM,在終端輸入sudo npm i -g rnpm;
? ?? ? ? ? ? ?c.自動在android文件中配置codePush,終端輸入:rnpm link react-native-code-push;
? ????????????d.查看安卓中配置;
? ? ????????????1.在android/app/build.gradle文件是否有apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"?
? ? ????????????2.在/android/settings.gradle文件是否有include ':react-native-code-push' project(':react-native-code-push').projectDir = new File(rootProject.projectDir,'../node_modules/react-native-code-push/android/app')
? ? ? ? ? ? ? e.配置deployment key
? ????????????? 1.獲取項目deployment key,終端輸入:code-push deployment ls (應用名稱)-k
? ? ????????????2.在MainApplication.java文件中修改deployment key
????????????f.修改versionName(codepush要三位數字的形式),在android/app/build.gradle中有個android.defaultConfig.versionName屬性
至此,android原生層的CodePush集成已經完成,接下來在React-native使用接入CodePush。
? ????4.RN中添加對應codePush
RN層Libraries/BatchedBridge包下面有3個JS文件:BatchedBridge.js、MessageQueue.js、NativeModules.js,它們封裝了通信橋在RN層的實現。在js中加載CodePush模塊:import codePush from 'react-native-code-push’,在componentDidMount中調用sync方法,后臺請求更新codePush.sync().?
? ????5.使用CodePush進行熱更新
CodePush支持兩種發布更新的方式,一是code-push release-react簡化方式,另一種是code-push release的復雜方式。
????????a.通過code-push release-react發布更新,此方法將打包與發布合二為一,在終端輸入:code-push release-react
eg.
????????其他形式語句:code-push release-react hello-world ios? --t 1.0.0 --dev false --d Production --des“更新內容:…”--m true.(注:參數--t為二進制.ipa或者.apk安裝包版本號;--dev為是否啟用開發者模式(默認為false);--d是要發布更新的環境分Production與Staging(默認為Staging);--des為更新說明;--m是強制更新。)
?b.生成bundle,上傳文件后的更新;
? ? 1.在項目下創建bundles文件夾,在其下在分別創建iOS和android兩個文件夾。生成文件夾命令:mkdir bundles(文件名稱)
? ? 2.生成對應的bundle,指令形式:react-native bundle --platform平臺--entry-file啟動文件--bundle-output打包js輸出文件--assets-dest資源輸出目錄--dev是否調試。終端輸入:react-native bundle --platform ios --entry-file index.js --bundle-output ./bundles/ios/index.jsbundle? --assets-dest ./bundles/ios --dev false
? ? 3.將生成的iOS文件添加到項目
????????將生成的android文件添加到項目,將index.jsbundle添加到android-->app-->src-->main-->assets下,其他資源文件放到android-->app-->src-->main-->res.? 筆者很好奇為什么jsbundle里的是js代碼,其他文件中的基本是圖片資源,安卓同事跟我說是放到res能正常加載。
? ? 4.上傳bundle,將生成的bundle文件上傳到CodePush。指令形式:code-push release-react --t <本更新包面向的舊版本號> --d <所處環境>? --des <本次更新說明>? --m<是否強制更新>。終端輸入:code-push release-react hello-world ios --t 1.0.0 --dev false --d Staging --des "" --m false。上傳成功后
注意:根據自己所在的環境對應不同的指令:Production(發布)Staging(灰度)
? 6.CodePush更新中的一些語句
1.查詢發布歷史版本:code-push deployment history ? <所處環境>
2.回滾到上一次:code-push rollback? ? <所處環境>
3.回滾到固定版本:code-push rollback ? <項目名稱> <所處環境> --targetRelease <Label>?? ? 。此處需要先查看歷史版本,然后填入對應的Label號
4.修改發布信息(label代表發布的更新版本,Target binary version代表app的版本號):code-push patch ? <所處環境>? --l ? --t <版本號>
修改前:
修改后:
5.將staging推倒production:code-push promote Staging Production
6.查看更新狀態:code-push deployment h ? <所處環境>
7.直接全量更新:code-push release-react
8.打包:react-native bundle --platform --entry-file <啟動文件> --bundle-output <打包js輸出文件>? --assets-dest <資源輸出目錄> --dev <是否調試>
9.上傳bundle到codePush:code-push release-react --t <本更新包面向的舊版本號> --dev <是否調試> --d <所處環境>? --des <描述> —m <是否強制更新>
10.code-push deployment history he-merchant-app Production(查看歷史發布版本)
注意: CodePush默認是更新Staging 環境的,如果發布生產環境的更新包,需要指定–d參數:–d Production,如果發布的是強制更新包,需要加上 –m true強制更新。
CodePush常用命令總結:
// 賬戶相關
code-push login 登陸
code-push loout 注銷
code-push access-key ls 列出登陸的token
code-push access-key rm <accessKye> 刪除某個 access-key
// app操作相關
code-push app add react-native在賬號里面添加一個新的app
code-push app remove 或者 rm 在賬號里移除一個 app
code-push app rename 重命名一個存在 app
code-push app list 或則 ls 列出賬號下面的所有 app
code-push app transfer 把app的所有權轉移到另外一個賬號
// 應用信息相關
code-push deployment add <appName> 部署
code-push deployment rm <appName> 刪除部署
code-push deployment rename <appName> 重命名
code-push deployment ls <appName> 列出應用的部署情況
code-push deployment ls <appName> -k 查看部署的key
code-push deployment history <appName> <deploymentName> 查看歷史版本
// 發布
code-push release-react -t 版本? -d 環境? --des 描述 -mtrue(強制更新)
// 清除歷史部署記錄
code-push deployment clear <appName> <所處環境>
// 回滾
code-push rollback <所處環境> --<codepush服務部署的版本號>