[ReactNative] 打離線包 和CodePush發布更新

首先,講React Native的發布更新,這就涉及到React Native的熱更新主要是怎么工作的,關鍵在于bundle的更新。我們先來看看ReactNative是怎么處理bundle文件(bundle文件用于資源管理)的。可以有如下兩種方式:1、app發版時,將bundle文件內置到app中,同時將圖片和js文件內置到app中(Android和iOS處理的不同)2、app在合適的時機,加載服務端最新的bundle文件
下面一張流程圖簡單介紹ReactNative的熱更新機制:(參考自:http://blog.csdn.net/codetomylaw/article/details/52115704)

ReactNative的熱更新.png

一、打離線包(打包bundle文件內置到app中)
離線包即本地存著一個離線包,保證沒有網絡的時候程序不會報錯。1、將js代碼打包到jsbundle文件中。在index.ios.js所在目錄下,執行以下命令(文件名自定義,使用codepush的時候最好命名為默認的main.jsbundle):
// 無圖片資源等react-native bundle --entry-file index.ios.js --platform ios --bundle-output main.jsbundle// 有圖片資源react-native bundle --entry-file index.ios.js --platform ios --bundle-output index.ios.bundle --platform ios --dev false --assets-dest ./ // 或者放bundle文件夾里(注意要先保證bundle文件夾存在!?。。?react-native bundle –entry-file index.ios.js –bundle-output ./bundle/iosBundle/index.ios.jsbundle –platform ios –assets-dest ./bundle/iosBundle –dev false /entry-file: RN的入口文件bundle-out: 輸出bundle文件的輸出路徑(bundle文件名和oc里面的代碼要對應)asset-dest:輸出的asset資源目錄/

2、添加到項目中。在xcode中添加assets【必須用Create folder references的方式,添加完是藍色文件夾圖標】和index.ios.jsbundle(或者main.jsbundle、命名不同)
網上參考的放bundle文件夾的目錄結構和項目結構如下:

bundle文件夾的目錄結構和項目結構(自網上).png

參考自:https://segmentfault.com/a/1190000004189538

個人利用第一句命令創建的包,目錄如下:


離線包目錄結構.png

3、修改AppDelegate.m文件(只使用離線包不使用熱更新的情況)
// URLForResource根據第一步對應的名字對應修改jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"index.ios" withExtension:@"jsbundle"];

4、模擬器或者真機調試都沒有問題。
順帶列舉下ios打包可能遇到的問題(雖然我都沒遇到哈):1)離線包如果開啟了chrome調試,會訪問調試服務器,而且會一直loading出不來。2)如果bundle的名字是main.jsbundle,app會一直讀取舊的,改名就好了。。。非常奇葩的問題,我重新刪了app,clean工程都沒用,就是不能用main.jsbundle這個名字。3)必須用Create folder references【藍色文件夾圖標】的方式引入圖片的assets,否則引用不到圖片4)執行bundle命令之前,要保證相關的文件夾都存在

二、使用CodePush實現熱更新

  1. 環境準備(Mac)
    1)安裝Code-push cli
    $ npm install -g code-push-cli

2) 注冊CodePush賬戶
$ code-push register

執行以上命令將會自動打開如下圖所示的注冊頁面:


注冊頁面.png

可以使用github或者Microsoft帳戶注冊(本文使用GitHub賬戶進行注冊),注冊成功后將會生成如下圖所示相應的access token:


access token.png

按照提示在終端輸入剛生成的access token(會自動登錄):
[圖片上傳中。。。(6)]輸入access token.png

3)添加CodePush應用
$ code-push app add XXX      //xxx 為你要熱部署的app name

結果如下:
[圖片上傳中。。。(7)]添加CodePush應用.png

  1. 安裝CodePush
    在項目更目錄(或者說package.json所在目錄)執行以下語句安裝CodePush,會自動對應修改package.json內容。
    npm install --save react-native-code-push

效果如下:


安裝CodePush.png

  1. 集成code-push 到工程文件
    CodePush集成到項目中,一般有三種方法:RNPM、CocoaPods 、"Manual"
    詳細可參考CodePush的Github:https://github.com/Microsoft/react-native-code-push

下文分別對其接入方法進行簡單介紹:個人感覺按情況分,如果是將React Native集成到原生項目中的項目,因為本身應該有用到cocoaPods,所以推薦使用cocoaPods接入,比較方便簡單。如果是純React Native項目,則可以考慮手動接入。(因為我測試用的是原生集成項目,所以就使用了cocoaPods)
方式一:cocoaPods接入
1)修改Podfile文件:(自己注意路徑哈)
pod 'CodePush', :path => './node_modules/react-native-code-push'

2)執行命令行更新pod:
pod install // 或者 pod install --verbose --no-repo-update

方式二:手動接入
1)將react-native-code-push文件夾中 CodePush.xcodeproj 直接拉入項目中Libraries中


CodePush.xcodeproj 拉入項目.png

2)在Link Binary With Libraries中添加Libraries/CodePush.xcodeproj /Products中的libCodePush.a以及libz.tbd。
[圖片上傳中。。。(10)]Link Binary With Libraries.png

3)在Build Settings的Header Search Paths那一項中加入(路徑要注意)
$(SRCROOT)/../node_modules/react-native-code-push

[圖片上傳中。。。(11)]Header Search Paths.png

方式三:RNPM接入
好像是官方推薦使用最簡單的方式,不過沒有試過哈1)安裝rnpm
$ npm -g install rnpm xcode

2)使用
$ rpm link

  1. 修改項目配置
    1)在命令行下使用code-push deployment ls <AppName> --displayKeys 查出Staging的值,在info.plist文件中添加CodePushDeploymentKey并且把Staging的值填入。2)在Info.plist中將Bundle versions string, short的值修改為1.0.0(或者其它,結構一樣為x.x.x,且和之后code push更新的版本要對應)
    [圖片上傳中。。。(12)]info.plist配置.png

  2. 修改OC代碼和JS代碼
    1)在加載 js bundle的類中 修改代碼
    a)首先,引入頭文件:

import "CodePush.h"

b)然后修改jsCodeLocation值:
//該文章是討論在Release下進行相關的操作,如果是debug版本加上如下代碼,系統在運行時候會自動切換。NSURL *jsCodeLocation;#ifdef DEBUG jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];#else jsCodeLocation = [CodePush bundleURL];#endif//如果本地js離線包不是命名main.jsbundle,需要對CodePush進行相應設置jsCodeLocation = [CodePush bundleURLForResource:@"index"];

2)在js文件中(該項目文件是index.ios.js) 修改代碼
a)引入對應頭文件
import codePush from "react-native-code-push";

b)在componentDidMount調用sync方法,當你的App啟動的時候會在后臺更新
componentDidMount(){ codePush.sync(); }

  1. 發布更新
    1)發布更新 (JavaScript-only)
    當你修改js文件的時候,并且想立刻發布。則僅僅需要以下的操作:
    將你修改的js文件(當前文件是index.ios.js)打包為二進制文件,放入指定的地方(當前位置為根目錄)。react-native bundle --platform ios --entry-file index.ios.js --bundle-output codepush.js --dev false

將二進制文件push到staging 環境中code-push release [--deploymentName ] [--description ] [--mandatory]eg:code-push release NativeTest codepush.js 1.0.0

2)發布更新 (JavaScript + images)
–assets-dest 就是你放圖片的位置(當前僅僅是做測試,實際上最好建個文件夾專門存入相關圖片)react-native bundle --platform ios --entry-file index.ios.js --bundle-output ./main.jsbundle --assets-dest ./<img 地址>// main.jsbundle 為自定義名字的bundle名

push bundle文件code-push <release/debug> <projectName(與注冊的app同名)><bundle文件名> <版本號>eg:code-push release NativeTest main.jsbundle 1.0.0

到這一步的時候,正常來說,該配置的都配置了,試著更新一個版本push到codepush上,運行下項目,就會出現效果。注意:如果出現找不到main.jsbundle的報錯,很大的原因就是沒有在本地打個離線包,詳細參考這篇文章的第一部分。(曾經因為這個原因,我看著報錯發呆了好久,上網也找不到任何說法??)

Q&A
CodePush更新規則[圖片上傳中。。。(13)]CodePush更新規則.png

更新后都需要重啟才能看到最新的變化 再次進入后要等一會。TODO:還要驗證后確定穩定時機。
查看歷史上傳過的版本:code-push deployment history NativeTest Staging

[圖片上傳中。。。(14)]查看歷史上傳過的版本.png

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容