CodePush 热更新

一 、配置CodePush

1、code-push-cli安装

$ sudo npm install code-push-cli -g

执行 code-push -v 显示版本号表示安装成功

2、注册 code-push账号

$ code-push register

会自动打开一个授权网页,让你选择使用哪种方式进行授权登录,一般选择GitHub就行,授权成功后就会得到授权码,回到终端输入授权码就注册并登录成功了

登录注册相关命令:

  • 注册 code-push register
  • 登陆 code-push login
  • 注销code-push logout
  • 列出 登陆的token code-push access-key ls
  • 删除某个 access-key code-push access-key rm <accessKey>

3、在CodePush服务器注册App

为了让CodePush服务器有我们的App,我们需要CodePush注册App,输入下面命令即可完成注册,这里需要注意如果我们的应用分为iOS和Android两个平台,这时我们需要分别注册两套key 应用添加成功后就会返回对应的production 和 Staging 两个key,production代表生产版的热更新部署,Staging代表开发版的热更新部署,在ios中将staging的部署key复制在info.plist的CodePushDeploymentKey值中,在android中复制在Application的getPackages的CodePush中。

  • 注册iOS APP:
code-push app add beginReact_ios ios react-native
  • 注册Android APP:
code-push app add beginReact_android Android react-native
  • 获取注册过的APP:
code-push app list
  • 获取注册APP的deployment key
code-push deployment ls beginReact_ios -k 
  • 其它CodePush管理APP指令:
code-push app add 在账号里面添加一个新的app
code-push app remove 或者 rm 在账号里移除一个app
code-push app rename 重命名一个存在app
code-push app list 或则 ls 列出账号下面的所有app
code-push app transfer 把app的所有权转移到另外一个账号

二、iOS集成

参考https://github.com/microsoft/react-native-code-push/blob/master/docs/setup-ios.md

  • 项目的版本号改为三位数,如1.0.1(大版本号)
  • 修改Appdelegate.m中sourceURLForBridge方法
  • 在info.plist中加入CodePushDeploymentKey,根据不同的热更新部署环境写入不同的key值
  • pod install
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
  #if DEBUG
    return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
  #else
    return [CodePush bundleURL];
  #endif
}

应用添加成功后就会返回对应的production 和 Staging 两个key,production代表生产版的热更新部署,Staging代表开发版的热更新部署。所以在info.plist中CodePushDeploymentKey对应了两个值,这时候就需要新增一个Release的新增Configuration环境,根据不同编译环境在info.plist中写入不同的值。新增Configuration环境参考

三、RN代码中集成CodePush

  • 集成
$ npm install react-native-code-push --save
$ react-native link react-native-code-push  //6.0以下需要
  • 根目录默认更新代码
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, Button} from 'react-native';
import CodePush from 'react-native-code-push'; // 引入code-push
import GlobalStyles from '../res/styles/GlobalStyles';
import NavigationBar from '../common/NavigationBar';
import NavigationUtil from '../navigators/NavigationUtil';
import ViewUtil from '../util/ViewUtil';
import DataModule from '../../js/bridge/DataModule';

let codePushOptions = {
  //设置检查更新的频率
  //ON_APP_RESUME APP恢复到前台的时候
  //ON_APP_START APP开启的时候
  //MANUAL 手动检查
  checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
};



type Props = {};
class App extends Component<Props> {
  //如果有更新的提示
  syncImmediate() {
    let state = DataModule.state;
    let codepushKey;
    if (state === 2) {
      codepushKey = 'fkPnIkl5C9f29EWoc4sWRaNavUjuUKbhizvT9w';
    } else {
      codepushKey = 'wCDlqzonF-hnaqbCIrRmRWEbiBkWUcs73L1xe';
    }

    CodePush.sync({
      //fkPnIkl5C9f29EWoc4sWRaNavUjuUKbhizvT9w 正式
      //wCDlqzonF-hnaqbCIrRmRWEbiBkWUcs73L1xe 测试

      //安装模式
      //ON_NEXT_RESUME 下次恢复到前台时
      //ON_NEXT_RESTART 下一次重启时
      //IMMEDIATE 马上更新
      mandatoryInstallMode: CodePush.InstallMode.IMMEDIATE,
      deploymentKey: codepushKey,
      //对话框
      updateDialog: {
        //是否显示更新描述
        appendReleaseDescription: true,
        //更新描述的前缀。 默认为"Description"
        descriptionPrefix: '更新内容:',
        //强制更新按钮文字,默认为continue
        mandatoryContinueButtonLabel: '立即更新',
        //强制更新时的信息. 默认为"An update is available that must be installed."
        mandatoryUpdateMessage: '必须更新后才能使用',
        //非强制更新时,按钮文字,默认为"ignore"
        optionalIgnoreButtonLabel: '稍后',
        //非强制更新时,确认按钮文字. 默认为"Install"
        optionalInstallButtonLabel: '后台更新',
        //非强制更新时,检查到更新的消息文本
        optionalUpdateMessage: '有新版本了,是否更新?',
        //Alert窗口的标题
        title: '更新提示',
      },
    });
  }
  componentWillMount() {
    CodePush.disallowRestart(); //禁止重启
    this.syncImmediate(); //开始检查更新
  }
  componentDidMount() {
    CodePush.allowRestart(); //在加载完了,允许重启
  }

  /*或者采用这一段代码
  componentDidMount() {
      CodePush.sync({
        updateDialog: {
          appendReleaseDescription: true,
          descriptionPrefix:'\n\n更新内容:\n',
          title:'更新',
          mandatoryUpdateMessage:'',
          mandatoryContinueButtonLabel:'更新',
        },
        mandatoryInstallMode:CodePush.InstallMode.IMMEDIATE,
        deploymentKey: 'iOS平台Key,部署环境(Production/Staging)',
      });
    }
  */
  render() {
    const {theme} = this.props.navigation.state.params;
    return (
      <View
        style={{
          flex: 1,
        }}>
        <NavigationBar
          style={theme.styles.navBar}
          leftButton={ViewUtil.getLeftButton(() =>
            NavigationUtil.goBack(this.props.navigation),
          )}
          title={'CodePush'}
        />{' '}
        <View style={styles.container}>
          <Text> {'iOS中Configuration状态' + DataModule.state} </Text>{' '}
          <Text> {'iOS中推送的key' + DataModule.key} </Text>{' '}
          <Text> {'iOS中版本号' + DataModule.version} </Text>
        </View>
      </View>
    );
  }
}

// 这一行必须要写
App = CodePush(codePushOptions)(App);

export default App;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    fontSize: 20,
    fontWeight: 'bold',
    textAlign: 'center',
  },
  welcome: {},
  instructions: {},
});

  • 手动更新流程
let codePushOptions = { checkFrequency: codePush.CheckFrequency.MANUAL };

class MyApp extends Component {
    onButtonPress() {
        codePush.sync({
            updateDialog: true,
            installMode: codePush.InstallMode.IMMEDIATE
        });
    }

    render() {
        return (
            <View>
                <TouchableOpacity onPress={this.onButtonPress}>
                    <Text>Check for updates</Text>
                </TouchableOpacity>
            </View>
        )
    }
}

MyApp = codePush(codePushOptions)(MyApp);

四、热更新

1、iOS热更新

(1) 在项目根路径下创建bundle文件夹,在bundle文件夹下创建ios文件夹android文件夹,用下面命令行生成assetsmain.jsbundle

$ react-native bundle --entry-file index.js --bundle-output ./bundle/ios/main.jsbundle --platform ios --assets-dest ./bundle/ios --dev false

(2)将生成的assetsmain.jsbundle文件拖入iOS工程,然后release出ipa
(3)修改要更新的内容,重新生成生成assetsmain.jsbundle文件,然后推送

$ code-push release-react <Appname> <Platform> --t <本更新包面向的旧版本号> --des <本次更新说明>
注意: CodePush默认是更新Staging 环境的,如果发布生产环境的更新包,需要指定--d参数:--d Production,如果发布的是强制更新包,需要加上 --m true强制更新

  • 使用Staging调试时
$ code-push release-react beginReact_ios ios --t 1.0.0 --des "更新内容"
  • 使用Production时
code-push release-react beginReact_ios ios --t 1.0.2 --dev false --d Production --des "这是第一个更新包" --m true
  • 查询历史
code-push deployment history beginReact_ios Staging
code-push deployment history beginReact_ios Production

2、android热更新

  • 生成bundle文件
    react-native bundle --entry-file index.js --bundle-output ./bundle/android/index.android.bundle
    --platform android --assets-dest ./bundle/android --dev false

*发布

 code-push release beginReact_android ./bundle/android 1.0.0 --deploymentName Production  --description "1.测试消" --mandatory true
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容