ReactNative基于CodePush实现热更新集成详解

来源:互联网 发布:网络的好处与坏处 编辑:程序博客网 时间:2024/05/16 15:21

[TOC]
参考 React Native中文官网(V0.42)

安装工具介绍

根据最新的官方文档和实际集成经验整理 http://www.jianshu.com/p/54cd13ed9e95

工具名称描述备注ChocolateyWindows上的包管理器(需翻墙)通常不安装,使用 npm 即可Python 2注意目前不支持Python 3版本不需安装NodeJsJavascript运行环境(runtime)自带 npmYarnFacebook提供的替代npm的工具,可以加速node模块的下载通常不安装使用,国内可通过设置设置npm镜像达到同样效果NPM包管理工具,主要用于解决NodeJS代码部署问题NodeJS中已安装react-native-cliReact Native的命令行工具用于执行创建、初始化、更新项目、运行打包服务(packager)等任务直接使用npm即可安装

Android 开发环境要求

  • Android Studio2.0或更高版本
  • [JDK] 1.8或更高版本
  • 必须安装Android Support Repository

环境变量相关

ANDROID_HOME制定到本地 \sdk 对应目录下
至少需配置:%Android_Home%\tools;%Android_Home%\platform-tools;


当前线上项目相关版本信息



环境搭建如上图,如有问题及时联系
下面是CodePush的Android客户端集成部分(热更新暂时使用微软的远程服务)


打开workspace目录初始化项目

$ react-native init RnApp


在对应的工作空间生成React Native工程目录


根目录下的 package.json 包管理配置文件

注意:使用命令行初始化的RN工程默认使用官网最新的组建版本,可能存在和某些三方组建的兼容性问题(如微软的CodePush);
如果希望指定RN组建版本初始化,可使用:$ react-native init RnApp --version 0.39.2

{    "name": "RnApp",//工程名称    "version": "0.0.1",//工程版本号    "private": true,//读写权限    "scripts": {        "start": "node node_modules/react-native/local-cli/cli.js start",//React Native启动入口        "test": "jest"    },    "dependencies": {        "react": "15.4.2",//依赖的react版本        "react-native": "0.42.3"//依赖的react-native版本    },    "devDependencies": {//开发调试依赖库        "babel-jest": "19.0.0",        "babel-preset-react-native": "1.9.1",        "jest": "19.0.2",        "react-test-renderer": "15.4.2"    },    "jest": {        "preset": "react-native"    }}

在初始化的RN工程的根目录下根据提示启动并运行Android项目


会自动启动一个本地开发服务器:如图代表开发服务器运行正常


使用 React Native 命令行工具启动项目异常处理

随着 React Native 版本不断升级,Android Studio 的版本变更,包括当前系统环境的差异性,导致在运行RN工程时会存在各种奇奇怪怪的问题;
此时需要将RN工程导入到当前系统环境的 Android studio 中直接运行,可以避免由于各个工具直接版本的差异导致运行失败的问题。


使用 Android Studio 打开初始化的 RN 工程


注意需要在 AS 中选择RN根目录结构下的 Android 打开


如图表示 React Native 工程在 IDE 中编译成功


RN初始化工程 App 下的 build.gradle 文件
可以看到RN的最小SDK构建版本是 16 对应的Android系统版本是 V_4.1.2

apply plugin: "com.android.application"import com.android.build.OutputFileapply from: "../../node_modules/react-native/react.gradle"def enableSeparateBuildPerCPUArchitecture = falsedef enableProguardInReleaseBuilds = falseandroid {    compileSdkVersion 23    buildToolsVersion "23.0.1"    defaultConfig {        applicationId "com.rnapp"        minSdkVersion 16        targetSdkVersion 22        versionCode 1        versionName "1.0"        ndk {            abiFilters "armeabi-v7a", "x86"        }    }    splits {        abi {            reset()            enable enableSeparateBuildPerCPUArchitecture            universalApk false  // If true, also generate a universal APK            include "armeabi-v7a", "x86"        }    }    buildTypes {        release {            minifyEnabled enableProguardInReleaseBuilds            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"        }    }    // applicationVariants are e.g. debug, release    applicationVariants.all { variant ->        variant.outputs.each { output ->            // For each separate APK per architecture, set a unique version code as described here:            // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits            def versionCodes = ["armeabi-v7a":1, "x86":2]            def abi = output.getFilter(OutputFile.ABI)            if (abi != null) {  // null for the universal-debug, universal-release variants                output.versionCodeOverride =                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode            }        }    }}dependencies {    compile fileTree(dir: "libs", include: ["*.jar"])    compile "com.android.support:appcompat-v7:23.0.1"    compile "com.facebook.react:react-native:+"  // From node_modules}// Run this once to be able to run the application with BUCK// puts all compile dependencies into folder libs for BUCK to usetask copyDownloadableDepsToLibs(type: Copy) {    from configurations.compile    into 'libs'}

如果将最小构建版本修改至低于 sdk16,则会导致工程构建失败,如图所示:
根据错误信息:如果需要使用 React Native 组件,则需要最低的sdk构建版本不低于16,
如果需要向下兼容,则需要使用工具重写“com.facebook.react”源码。


在RN项目根目录下开启调试服务器

$ npm start


使用AS直接运行RnApp,安装成功后部分手机需要用户授权悬浮窗权限


授权成功后重新打开项目


如果出现不能获取调试桥的错误提示,请手动设置调试端口号为:8081 后点击 RELOAD(R,R)

设置调试服务器端口方式一:adb reverse tcp:8081 tcp:8081


等待 JsBundle 文件解析完成即可渲染出 RN 页面


设置调试服务器端口方式二:在开发模式下摇晃手机调用出开服者选项设置项


设置调试服务器主机名和端口号:


按照如下格式输入主机名和端口号:

注意:所输入的主机名一定是当前运行开发服务器计算机的IP地址,并且调试机和开发服务器需要要在同一个局域网环境下;
方式二优点:如果设置成功,在调试过程中就不需使用USB数据线和计算机连接了。


至此,一个RN工程的 hello world 工程就完成了...

备注:初始化后的RN工程启动文件和启动页源码

程序启动入口: Application.java 文件:

package com.rnapp;import android.app.Application;import com.facebook.react.ReactApplication;import com.facebook.react.ReactNativeHost;import com.facebook.react.ReactPackage;import com.facebook.react.shell.MainReactPackage;import com.facebook.soloader.SoLoader;import java.util.Arrays;import java.util.List;public class MainApplication extends Application implements ReactApplication {  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {    @Override    public boolean getUseDeveloperSupport() {      return BuildConfig.DEBUG;    }    @Override    protected List<ReactPackage> getPackages() {      return Arrays.<ReactPackage>asList(          new MainReactPackage()      );    }  };  @Override  public ReactNativeHost getReactNativeHost() {    return mReactNativeHost;  }  @Override  public void onCreate() {    super.onCreate();    SoLoader.init(this, /* native exopackage */ false);  }}

RN页面入口: ReactActivity.java 文件子类:

package com.rnapp;import com.facebook.react.ReactActivity;public class MainActivity extends ReactActivity {    /**     * Returns the name of the main component registered from JavaScript.     * This is used to schedule rendering of the component.     */    @Override    protected String getMainComponentName() {        return "RnApp";    }}

下面是 CodePush 集成详解

参考文档:React Native热更新部署/热更新-CodePush最新集成总结(新)

CodePush 简介

CodePush 是微软提供的一套用于热更新 React Native 和 Cordova 应用的服务。
CodePush 是提供给 React Native 和 Cordova 开发者直接部署移动应用更新给用户设备的云服务。CodePush 作为一个中央仓库,开发者可以推送更新 (JS, HTML, CSS and images),应用可以从客户端 SDK 里面查询更新。CodePush 可以让应用有更多的可确定性,也可以让你直接接触用户群。在修复一些小问题和添加新特性的时候,不需要经过二进制打包,可以直接推送代码进行实时更新。

安装 CodePush CLI

参数 -g 表示安装位置为全局,请不要安装在当前项目目录下


创建CodePush账号

涉及到公司开发者账号,此处省略截图

  • 在终端输入$ code-push register,会打开如下注册页面让你选择授权账号。
  • 授权通过之后,CodePush会告诉你 access key ,复制此key到终端即可完成注册。
  • 然后终端输入 $ code-push login 进行登陆,登陆成功后,你的session文件将会写在 /Users/你的用户名/.code-push.config。

在CodePush服务器注册app

终端输入:$ code-push app add RnApp完成注册并获取部署键值

Production 表示生产环境 唯一识别的部署键值:K1pkiaHC2-w-0M3iRaABluolNtRL4JHzHx0MG
Staging 表示开发环境 唯一识别的部署键值:_lvQXBDZ0m_2rFdBlnZ5pkd0fa-n4JHzHx0MG
建议:Android和IOS使用单独的项目部署获取两套 Deployment Key


安装 react-native-code-push插件

切换到RN工程根目录 终端输入命令:$ npm install react-native-code-push --save

注意:--save 参数表示是否将当前依赖写入 package.json 文件


将会在 package.json 文件中写入依赖配置


注意:切换到RN工程根目录 终端输入命令:$ rnpm link react-native-code-push 将会自动帮我们进行code-push插件在原生中的gradle配置,
但是不建议使用,我们可以手动的进行 CodePush 的 gradle 配置以达到同样的效果。

这是引入RN官网的文档:
安装完node后建议设置npm镜像以加速后面的过程(或使用科学上网工具)。注意:不要使用cnpm!cnpm安装的模块路径比较奇怪,packager不能正常识别!
即:不建议使用类似 cnpm 活着 rnpm 进行相关模块的操作。

在原生项目中手动集成 CodePush

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')

3. 在 android/app/build.gradle文件里面添如下代码将CodePush添加项目编译:

 compile project(':react-native-code-push')

4. 运行 $ code-push deployment ls RnApp -k 命令获取 部署秘钥.


5. 在 MainApplication.java 中添加如下代码:

 //注意需要将部署键值替换成自己的项目的唯一键值 new CodePush("deployment-key-here", MainApplication.this, BuildConfig.DEBUG)

6. 在index.Android.js 中调用更新服务


相应代码可直接复制使用

componentDidMount(){    codePushUpdate();  }  //远程服务检测更新  codePushUpdate(){    codePush.sync({      installMode: codePush.InstallMode.IMMEDIATE,      updateDialog: true     },     (status) => {      switch (status) {        case codePush.SyncStatus.CHECKING_FOR_UPDATE:            console.log('codePush.SyncStatus.CHECKING_FOR_UPDATE');          break;        case codePush.SyncStatus.AWAITING_USER_ACTION:          console.log('codePush.SyncStatus.AWAITING_USER_ACTION');          break;        case codePush.SyncStatus.DOWNLOADING_PACKAGE:          console.log('codePush.SyncStatus.DOWNLOADING_PACKAGE');          break;         case codePush.SyncStatus.INSTALLING_UPDATE:          console.log('codePush.SyncStatus.INSTALLING_UPDATE');          break;        case codePush.SyncStatus.UP_TO_DATE:          console.log('codePush.SyncStatus.UP_TO_DATE');          break;        case codePush.SyncStatus.UPDATE_IGNORED:          console.log('codePush.SyncStatus.UPDATE_IGNORED');          break;        case codePush.SyncStatus.UPDATE_INSTALLED:          console.log('codePush.SyncStatus.UPDATE_INSTALLED');          break;        case codePush.SyncStatus.SYNC_IN_PROGRESS:          console.log('codePush.SyncStatus.SYNC_IN_PROGRESS');          break;        case codePush.SyncStatus.UNKNOWN_ERROR:          console.log('codePush.SyncStatus.UNKNOWN_ERROR');          break;      }     },     ({ receivedBytes, totalBytes, }) => {      console.log('receivedBytes / totalBytes: ------------    ' + receivedBytes+'/'+totalBytes);      }    );  }

8. 在RN更目录下新建两个文件夹

注意:将项目的VersionName修改为三位数!


9. CodePush命令行打JsBundle包(存于本地)

$ react-native bundle --platform android --entry-file index.android.js --bundle-output ./bundles/index.android.bundle  --assets-dest ./bundles --dev false

10. 执行如下命令部署到微软服务器

$ code-push release PatientMRB ./bundles 1.0.0 --deploymentName Staging --description “RN热更新测试“ --mandatory true

11. 运行项目日志输出如下


至此:一个简单的RN集成CodePush实现热更新已经完成...
后续期待和大家一起爬坑...


附录:CodePush 常用命令总结

  • code-push login
  • code-push logout
  • code-push access-key ls 列出登陆的token
  • code—push access-key rm <accessKey> 删除某个access-key
  • code-push app ls
  • code-push app add <appName>
  • code-push app rm <appName>
  • code-push app rename <appName>
  • code-push app transfer 转移app所有权到另一个账号
  • code-push deployment add <appName> 部署
  • code-push deployment rename <appName> 重命名
  • code-push deployment ls <appName>
  • code-push deployment ls <appName> -k
  • code-push deployment history <appName> <deploymentName>(Production||Staging)
  • code-push rollback <appName> <deploymentName> “appName”中的测试||生产环境的部署执行回滚
  • code-push rollback <appName> <deploymentName> —targetRelease v6 回滚到指定的部署标签

简书处女座,如有书写不妥的地方请留言更正,同时欢迎拍砖吐槽...
最后有一个愿望:希望借此爱上技术写作...

0 0
原创粉丝点击