react-native之熱更新

什麼是熱更新

簡單說就是不須要去應用市場從新下載,直接打開app就會下載更新的內容而後進入app,相似於常常玩遊戲,遊戲裏須要更新,而後就有個進度條在讀取。總結就是能夠不經過應用市場來進行升級,極大的提高了app修bug和賦予新功能的能力前端

RN熱更新的原理是什麼

一個完整的RN-app程序一般包含如下幾個部分:react

  • native代碼部分android

  • js代碼部分-rn代碼、依賴的第三方庫、業務代碼等ios

  • 圖片資源部分react-native

native代碼發生了變更

若是你的項目的native代碼發生了變更,對不起,熱更新不能知足你的需求,你只能硬更新,讓用戶從新下載新的來覆蓋舊的app。截止的當前日期,RN的版本還只是0.32,距離1.0還很遙遠。因此常常會有須要用到的功能,而RN原生沒有封裝,因此只能親自來寫,固然,若是咱們有一個完整的無線團隊,那麼是極好的,直接去把無線團隊裏的類庫中篩選個一些可能會用到的功能,先提早封裝進來,儘可能的減小熱更新的次數。app

圖片資源或者是js發生變更

而若是咱們是想修改圖片資源或者是js的代碼部分,好的,可使用熱更新,那麼既然是熱更新,我就置想去修改變更的內容,計算方法:新版本(V3.1) - 舊版本(v3.0) = 增量包異步

好的,以上都是理論原理內容,因爲項目期只有2我的在作RN前端方面的開發,因此沒有足夠的時間去開發公司內部的熱更新。因此使用了第三方的組件react-native-pushyide

如何使用react-native-pushy

註冊一個pushy帳號

pushy函數

配置Bundle URL(iOS)

在工程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
  // ... 其它代碼
}

配置Bundle URL(Android)

0.29及之後版本:在你的MainApplication中增長以下代碼:

// ... 其它代碼

import cn.reactnative.modules.update.UpdateContext;
public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    protected String getJSBundleFile() {
        return UpdateContext.getBundleUrl(MainApplication.this);
    }
    // ... 其它代碼
  }
}

0.28及之前版本:在你的MainActivity中增長以下代碼:

// ... 其它代碼

import cn.reactnative.modules.update.UpdateContext;

public class MainActivity extends ReactActivity {

    @Override
    protected String getJSBundleFile() {
        return UpdateContext.getBundleUrl(this);
    }
    // ... 其它代碼
}

添加熱更新功能

頁面須要引用react-native-update模塊

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

一般狀況下,熱更新的判斷須要在app啓動上來就要進行判斷,那麼大多數都會寫在index.android.js中

componentWillMount(){
    //去除debug時候的警告,測試的時候建議打開,hotloading的時候能夠關掉
    // console.disableYellowBox = true;
    // 2s 後若是尚未響應 則提示並取消
    let freshedFlag = false;
    let timeout = setTimeout(() => {
         timeout && clearTimeout(timeout);
         
         if (freshedFlag) return;

         freshedFlag = true;

         console.log('超時');
         
         //作些什麼,好比setState讓頁面跳過

    }, REQ_TIMEOUT);
    
    //防止反觸發,就是更新完了回滾
    markSuccess();
    
    //異步函數checkUpdate能夠檢查當前版本是否須要更新
    
    checkUpdate(appKey).then(info => {
      // freshedFlag 爲 true 則說明超時
      console.log('timeout'+freshedFlag);
      if (freshedFlag) {
          return;
      } else {
          freshedFlag = true;
      }
      //包過時,須要下載最新版的應用(非熱更新)
      if (info.expired) {
          //進度條隱藏,新版本彈窗,提供下載地址
          this.setState({
              progressState:false,
              showDialog:true,
              downloadUrl:info.downloadUrl
          })
      }
      //當前版本是最新版本,無需熱更新 
      else if (info.upToDate) {
          this.setState({
            progressState:false,
            progressNum: 100,
            welcome:false,
            update:false
          })
      } else {
          //須要熱更新了
          this.doUpdate(info)
      }

    }).catch(err => {
      this.setState({
        progressState:false,
        welcome:false,
      })
    });
  }
  //熱更新函數
  doUpdate = info => {
    
    //作點什麼,讓你的UI顯示出來,提供個假性的進度條什麼的
    
    downloadUpdate(info).then(hash => {
        //下載完版本返回一個hash字符串,是當前笨笨的惟一標示,而後切換版本
      switchVersion(hash);
    }).catch(err => {
      this.setState({
        progressState:false,
        welcome:false,
      })
    });
  };

就理論而言,熱更新操做到此結束,可是實際使用過程當中,5000個用戶大概會有100個丟掉的可能性。不是特別的準,也存在少許用戶回滾版本的行爲。據說公司其餘部門的團隊作的app用的是codePush,後期也能夠多研究一下。

相關文章
相關標籤/搜索