React Native 插曲 打離線包和CodePush發布更新

用了兩天才搞定了這些瑣碎的操作,從真機調試到利用CodePush進行熱更新。。。知道最后才發現一個血的教訓:即使用了CodePush,本地也必須要有一個離線包才行,即本地需要打包一個main.jsbundle放進項目中,才可以成功運行。

首先,講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(會自動登錄):

輸入access token.png

3)添加CodePush應用

$ code-push app add XXX      //xxx 為你要熱部署的app name

結果如下:


添加CodePush應用.png

2. 安裝CodePush

在項目更目錄(或者說package.json所在目錄)執行以下語句安裝CodePush,會自動對應修改package.json內容。

npm install --save react-native-code-push

效果如下:

安裝CodePush.png

3. 集成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。

Link Binary With Libraries.png

3)在Build Settings的Header Search Paths那一項中加入(路徑要注意)

$(SRCROOT)/../node_modules/react-native-code-push

Header Search Paths.png

方式三:RNPM接入

好像是官方推薦使用最簡單的方式,不過沒有試過哈
1)安裝rnpm

$ npm -g install rnpm xcode

2)使用

$ rpm link

4. 修改項目配置

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更新的版本要對應)

info.plist配置.png

5. 修改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();
  }

6. 發布更新

1)發布更新 (JavaScript-only)

當你修改js文件的時候,并且想立刻發布。則僅僅需要以下的操作:

  1. 將你修改的js文件(當前文件是index.ios.js)打包為二進制文件,放入指定的地方(當前位置為根目錄)。
react-native bundle --platform ios --entry-file index.ios.js --bundle-output codepush.js --dev false
  1. 將二進制文件push到staging 環境中
code-push release [--deploymentName ] [--description ]  [--mandatory]
eg:
code-push release NativeTest codepush.js 1.0.0

// 上面代碼運行有問題的話,試試把codepush.js后綴改成codepush.jsbundle。。好像目前版本和我上年底的要求不同了

2)發布更新 (JavaScript + images)

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

  1. CodePush更新規則


    CodePush更新規則.png
  2. 更新后都需要重啟才能看到最新的變化 再次進入后要等一會。TODO:還要驗證后確定穩定時機。
  3. 查看歷史上傳過的版本:

code-push deployment history NativeTest Staging

查看歷史上傳過的版本.png

更多的CodePush相關命令推薦參考以下幾篇文章:
Code Push 熱更新使用詳細說明和教程
app實現熱更新codepush
以及CodePush的Github:
https://github.com/Microsoft/react-native-code-push

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,516評論 2 379

推薦閱讀更多精彩內容