RN精進(jìn)筆記(十二)熱更新篇

使用Pushy進(jìn)行熱更新

Pushyreactnative.cn提供的付費項目哥蔚,可以用來進(jìn)行熱更新慨畸。該平臺的實現(xiàn)原理比起CodePush要簡單些莱坎,有利于仿照該系統(tǒng)重寫一個熱更新平臺。該熱更新平臺涉及iOS native端寸士, 安卓native端和react-native端以及服務(wù)端增量更新型奥。

參考文獻(xiàn)
  1. https://github.com/reactnativecn/react-native-pushy/blob/master/docs/guide3.md
  2. https://github.com/reactnativecn/react-native-pushy
  3. http://update.reactnative.cn/dashboard
安裝Pushy

在你的項目根目錄下運行以下命令(不要輸入開頭的美元符號):

#第一個命令每臺電腦只需要執(zhí)行一次
$ npm install -g react-native-update-cli rnpm
$ npm install --save react-native-update
$ rnpm link react-native-update
配置Bundle URL(iOS)

// 文檔建設(shè)中

在工程target的Build Phases->Link Binary with Libraries中加入libz.tbd瞳收、libbz2.1.0.tbd

在你的AppDelegate.m文件中增加如下代碼:

// ... 其它代碼

#import "RCTHotUpdate.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if DEBUG
  // 原來的jsCodeLocation
  jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];
#else
  jsCodeLocation=[RCTHotUpdate bundleURL];
#endif
  // ... 其它代碼
}
登錄與創(chuàng)建應(yīng)用

在你的項目根目錄下運行以下命令:

$ pushy login
email: <輸入你的注冊郵箱>
password: <輸入你的密碼>
#我依稀記得我的登錄賬號和密碼分別是:
$ email: 1320681113@qq.com
$ password: gL13512740718

這會在項目文件夾下創(chuàng)建一個.update文件,注意不要把這個文件上傳到Git等CVS系統(tǒng)上厢汹。你可以在.gitignore末尾增加一行.update來忽略這個文件。

登錄之后可以創(chuàng)建應(yīng)用谐宙。注意iOS平臺和安卓平臺需要分別創(chuàng)建:

$ pushy createApp --platform ios
App Name: <輸入應(yīng)用名字>
$ pushy createApp --platform android
App Name: <輸入應(yīng)用名字>

$ pushy createApp --platform ios
App Name: testHotUpdate 
Created app 1140
#這時我再刷新程序頁面發(fā)現(xiàn)已經(jīng)可以正常運行烫葬,不報錯了,喜大普奔凡蜻。
#運行pushy的testHotUpdate一直報錯搭综,提示說沒有找到 "update.json"文件,去js/index.js發(fā)現(xiàn)確實需要import Update from '../../update.json'划栓,因為我根本沒有注冊這個程序兑巾,所以沒有生成update.json,于是我在該項目根目錄下pushy login && pushy createApp --platfrom ios App Name: testHotUpdate之后再刷新程序發(fā)現(xiàn)已經(jīng)可以正常運行忠荞。

如果你已經(jīng)在網(wǎng)頁端(指Pushy的網(wǎng)站http://update.reactnative.cn/dashboard蒋歌,這里我發(fā)現(xiàn)我已經(jīng)添加了一個應(yīng)用testHotUpdate)或者其它地方創(chuàng)建過應(yīng)用,也可以直接選擇應(yīng)用:

$ pushy selectApp --platform ios
1) 魚多多(ios)
3) 招財旺(ios)

Total 2 ios apps
Enter appId: <輸入應(yīng)用前面的編號> 

選擇或者創(chuàng)建國應(yīng)用后委煤,你講可以在文件夾下看到update.json文件堂油,其內(nèi)容格式如下:

{
    "ios": {
        "appId": 1,
        "appKey": "<一串隨機(jī)字符串>"
    },
    "android": {
        "appId": 2,
        "appKey": "<一串隨機(jī)字符串>"
    }
}

你可以安全的把update.json上傳到Git等CVS系統(tǒng)上,與你的團(tuán)隊共享這個文件碧绞,它不包含任何敏感信息府框。當(dāng)然,他們在使用任何功能之前讥邻,都必須首先輸入pushy login進(jìn)行登錄迫靖。

添加熱更新功能

通過上部分的準(zhǔn)備工作,該部分主要講如何給工程添加熱更新功能兴使。

獲取appKey

檢查更新時必須提供你的appKey系宜,這個值保存在update.json中,并且根據(jù)平臺不同而不同鲫惶。你可以用如下的代碼獲闰谑住:

import React, {
  Platform,
} from 'react-native';

import _updateConfig from './update.json';
const {appKey} = _updateConfig[Platform.OS];

如果你不使用pushy命令行,你也可以從網(wǎng)頁端查看到兩個應(yīng)用appKey欠母,并根據(jù)平臺的不同來選擇欢策。

檢查更新、下載更新

異步函數(shù)checkUpdate可以檢測當(dāng)前版本是否需要更新:

checkUpdate(appKey)
    .then(info => {
    })

返回的info有三種情況:

  1. {expired: true}:該應(yīng)用包(原生部分)已過期赏淌,需要前往應(yīng)用市場下載新的版本踩寇。
  2. {upToDate: true}:當(dāng)前已經(jīng)更新到最新,無需進(jìn)行更新六水。
  3. {update: true}:當(dāng)前有新版本可以更新俺孙。info的name辣卒、description字段可 以用于提示用戶,而metaInfo字段則可以根據(jù)你的需求自定義其它屬性(如是否靜默更新睛榄、 是否強(qiáng)制更新等等)荣茫。另外還有幾個字段,包含了完整更新包或補(bǔ)丁包的下載地址场靴, react-native-update會首先嘗試耗費流量更少的更新方式啡莉。將info對象傳遞給downloadUpdate作為參數(shù)即可。
切換版本

downloadUpdate的返回值是一個hash字符串旨剥,它是當(dāng)前版本的唯一標(biāo)識咧欣。

你可以使用switchVersion函數(shù)立即切換版本(此時應(yīng)用會立即重新加載),或者選擇調(diào)用 switchVersionLater轨帜,讓應(yīng)用在下一次啟動的時候再加載新的版本魄咕。

首次啟動、回滾

在每次更新完畢后的首次啟動時蚌父,isFirstTime常量會為true哮兰。 你必須在應(yīng)用退出前合適的任何時機(jī),調(diào)用markSuccess梢什,否則應(yīng)用下一次啟動的時候?qū)M(jìn)行回滾操作奠蹬。 這一機(jī)制稱作“反觸發(fā)”,這樣當(dāng)你應(yīng)用啟動初期即遭遇問題的時候嗡午,也能在下一次啟動時恢復(fù)運作囤躁。

你可以通過isFirstTime來獲知這是當(dāng)前版本的首次啟動,也可以通過isRolledBack來獲知應(yīng)用剛剛經(jīng)歷了一次回滾操作荔睹。 你可以在此時給予用戶合理的提示狸演。

完整示例
import React, {
  Component,
} from 'react';

import {
  AppRegistry,
  StyleSheet,
  Platform,
  Text,
  View,
  Alert,
  TouchableOpacity,
  Linking,
} from 'react-native';

import {
  isFirstTime,
  isRolledBack,
  packageVersion,
  currentVersion,
  checkUpdate,
  downloadUpdate,
  switchVersion,
  switchVersionLater,
  markSuccess,
} from 'react-native-update';

import _updateConfig from './update.json';
const {appKey} = _updateConfig[Platform.OS];

class MyProject extends Component {
  componentWillMount(){
    if (isFirstTime) {
      Alert.alert('提示', '這是當(dāng)前版本第一次啟動,是否要模擬啟動失敗?失敗將回滾到上一版本', [
        {text: '是', onPress: ()=>{throw new Error('模擬啟動失敗,請重啟應(yīng)用')}},
        {text: '否', onPress: ()=>{markSuccess()}},
      ]);
    } else if (isRolledBack) {
      Alert.alert('提示', '剛剛更新失敗了,版本被回滾.');
    }
  }
  doUpdate = info => {
    downloadUpdate(info).then(hash => {
      Alert.alert('提示', '下載完畢,是否重啟應(yīng)用?', [
        {text: '是', onPress: ()=>{switchVersion(hash);}},
        {text: '否',},
        {text: '下次啟動時', onPress: ()=>{switchVersionLater(hash);}},
      ]);
    }).catch(err => { 
      Alert.alert('提示', '更新失敗.');
    });
  };
  checkUpdate = () => {
    checkUpdate(appKey).then(info => {
      if (info.expired) {
        Alert.alert('提示', '您的應(yīng)用版本已更新,請前往應(yīng)用商店下載新的版本', [
          {text: '確定', onPress: ()=>{info.downloadUrl && Linking.openURL(info.downloadUrl)}},
        ]);
      } else if (info.upToDate) {
        Alert.alert('提示', '您的應(yīng)用版本已是最新.');
      } else {
        Alert.alert('提示', '檢查到新的版本'+info.name+',是否下載?\n'+ info.description, [
          {text: '是', onPress: ()=>{this.doUpdate(info)}},
          {text: '否',},
        ]);
      }
    }).catch(err => { 
      Alert.alert('提示', '更新失敗.');
    });
  };
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          歡迎使用熱更新服務(wù)
        </Text>
        <Text style={styles.instructions}>
          這是版本一 {'\n'}
          當(dāng)前包版本號: {packageVersion}{'\n'}
          當(dāng)前版本Hash: {currentVersion||'(空)'}{'\n'}
        </Text>
        <TouchableOpacity onPress={this.checkUpdate}>
          <Text style={styles.instructions}>
            點擊這里檢查更新
          </Text>
        </TouchableOpacity>
      </View>
    );
  }
}

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,
  },
});

AppRegistry.registerComponent('MyProject', () => MyProject);

現(xiàn)在,你的應(yīng)用已經(jīng)可以通過update服務(wù)檢查版本并進(jìn)行更新了僻他。下一步宵距,你可以開始嘗試發(fā)布應(yīng)用包和版本,請參閱發(fā)布應(yīng)用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吨拗,一起剝皮案震驚了整個濱河市满哪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌劝篷,老刑警劉巖哨鸭,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異娇妓,居然都是意外死亡像鸡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進(jìn)店門哈恰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來只估,“玉大人志群,你說我怎么就攤上這事』赘疲” “怎么了锌云?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長夸楣。 經(jīng)常有香客問我宾抓,道長,這世上最難降的妖魔是什么豫喧? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮幢泼,結(jié)果婚禮上紧显,老公的妹妹穿的比我還像新娘。我一直安慰自己缕棵,他們只是感情好孵班,可當(dāng)我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著招驴,像睡著了一般篙程。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上别厘,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天虱饿,我揣著相機(jī)與錄音,去河邊找鬼触趴。 笑死氮发,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的冗懦。 我是一名探鬼主播爽冕,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼披蕉!你這毒婦竟也來了颈畸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤没讲,失蹤者是張志新(化名)和其女友劉穎眯娱,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體食零,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡困乒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了贰谣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娜搂。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡迁霎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出百宇,到底是詐尸還是另有隱情考廉,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布携御,位于F島的核電站昌粤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏啄刹。R本人自食惡果不足惜涮坐,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望誓军。 院中可真熱鬧袱讹,春花似錦、人聲如沸昵时。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽壹甥。三九已至救巷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間句柠,已是汗流浹背浦译。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留俄占,地道東北人管怠。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像缸榄,于是被迫代替她去往敵國和親渤弛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,193評論 25 707
  • 開發(fā)React Native (以下簡稱 RN)主要就是看中他的動態(tài)更新和跨平臺以及代碼復(fù)用甚带,本文介紹RN的動態(tài)更...
    沐風(fēng)雨木閱讀 2,222評論 2 1
  • 開發(fā)完了她肯,該看看如何上線和維護(hù)一個項目了。 (一)打包apk 乍一看目錄結(jié)構(gòu)鹰贵,有一個Android的gradle項...
    大杰哥_2bec閱讀 9,660評論 1 8
  • 前段時間寫作老師推薦了一本《姥姥語錄》晴氨,是主持人倪萍寫的,其實對于倪萍我不是很了解碉输,可能是因為在她很出名的時候籽前,我...
    秋千小書閱讀 931評論 2 0
  • "我言秋日勝春朝",自古文人都喜歡秋天,因為他代表收獲枝哄,也代表了抒情肄梨。涼風(fēng)習(xí)習(xí),天高云淡挠锥,一抬頭众羡,你看到的是...
    云舒與小白閱讀 193評論 0 0