React-Native 热更新

热更新解决方案

采用 微软react-native-code-push + 自建code-push-server服务 进行RN热更新管理

1、本地安装code-push-server与code-push-cli

npm install code-push-server -g

npm install code-push-cli -g

2、初始化mysql数据库(先自行安装mysql,建议版本5.6)

  • 先启动MySQL服务
  • code-push-server-db init --dbhost localhost --dbname codepush --dbuser root --dbpassword xxxxxx
  • 如果MySql版本为8.0,先执行 alter user 'root'@'localhost' identified with mysql_native_password by 'xxxxxx';

3、启动code-push-server服务

  • 先配置config.js (C:\Users\Administrator\AppData\Local\Yarn\Data\global\node_modules\code-push-server\config\config.js)
  • var os = require('os');
    
    var config = {};
    config.development = {
      // Config for database, only support mysql.
      db: {
        username: process.env.RDS_USERNAME || "root",
        password: process.env.RDS_PASSWORD || "xxxxx",
        database: process.env.DATA_BASE || "codepush",
        host: process.env.RDS_HOST || "127.0.0.1",
        port: process.env.RDS_PORT || 3306,
        dialect: "mysql",
        logging: false,
        operatorsAliases: false,
      },
      // Config for qiniu (http://www.qiniu.com/) cloud storage when storageType value is "qiniu".
      qiniu: {
        accessKey: "",
        secretKey: "",
        bucketName: "",
        downloadUrl: "" // Binary files download host address.
      },
      // Config for Amazon s3 (https://aws.amazon.com/cn/s3/) storage when storageType value is "s3".
      s3: {
        accessKeyId: process.env.AWS_ACCESS_KEY_ID,
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
        sessionToken: process.env.AWS_SESSION_TOKEN, //(optional)
        bucketName: process.env.BUCKET_NAME,
        region: process.env.REGION,
        downloadUrl: process.env.DOWNLOAD_URL, // binary files download host address.
      },
      // Config for Aliyun OSS (https://www.aliyun.com/product/oss) when storageType value is "oss".
      oss: {
        accessKeyId: "",
        secretAccessKey: "",
        endpoint: "",
        bucketName: "",
        prefix: "", // Key prefix in object key
        downloadUrl: "", // binary files download host address.
      },
      // Config for tencentyun COS (https://cloud.tencent.com/product/cos) when storageType value is "oss".
      tencentcloud: {
        accessKeyId: "",
        secretAccessKey: "",
        bucketName: "",
        region: "",
        downloadUrl: "", // binary files download host address.
      },
      // Config for local storage when storageType value is "local".
      local: {
        // Binary files storage dir, Do not use tmpdir and it's public download dir.
        // 需要配置bundle包本地存储位置
        storageDir: process.env.STORAGE_DIR || "/Users/captain/workspaces/storage",
        // Binary files download host address which Code Push Server listen to. the files storage in storageDir.
        // 配置服务器下载地址
        downloadUrl: process.env.LOCAL_DOWNLOAD_URL || "http://10.180.51.237:3000/download",
        // public static download spacename.
        public: '/download'
      },
      jwt: {
        // Recommended: 63 random alpha-numeric characters
        // Generate using: https://www.grc.com/passwords.htm
        tokenSecret: process.env.TOKEN_SECRET ||'CeSCpLaHcbOujnQPTQp0FFDYL9YNxjsxBptL58kGShe4Y3Mds1PQPu84UbktZyg'
      },
      common: {
        /*
         * tryLoginTimes is control login error times to avoid force attack.
         * if value is 0, no limit for login auth, it may not safe for account. when it's a number, it means you can
         * try that times today. but it need config redis server.
         */
        tryLoginTimes: 0,
        // CodePush Web(https://github.com/lisong/code-push-web) login address.
        //codePushWebUrl: "http://127.0.0.1:3001/login",
        // create patch updates's number. default value is 3
        diffNums: 3,
        // data dir for caclulate diff files. it's optimization.
        dataDir: process.env.DATA_DIR || os.tmpdir(),
        // storageType which is your binary package files store. options value is ("local" | "qiniu" | "s3"| "oss" || "tencentcloud")
        storageType: process.env.STORAGE_TYPE || "local",
        // options value is (true | false), when it's true, it will cache updateCheck results in redis.
        updateCheckCache: false,
        // options value is (true | false), when it's true, it will cache rollout results in redis
        rolloutClientUniqueIdCache: false,
      },
      // Config for smtp email,register module need validate user email project source https://github.com/nodemailer/nodemailer
      smtpConfig:{
        host: "smtp.aliyun.com",
        port: 465,
        secure: true,
        auth: {
          user: "",
          pass: ""
        }
      },
      // Config for redis (register module, tryLoginTimes module)
      redis: {
        default: {
          host: "127.0.0.1",
          port: 6379,
          retry_strategy: function (options) {
            if (options.error.code === 'ECONNREFUSED') {
              // End reconnecting on a specific error and flush all commands with a individual error
              return new Error('The server refused the connection');
            }
            if (options.total_retry_time > 1000 * 60 * 60) {
                // End reconnecting after a specific timeout and flush all commands with a individual error
                return new Error('Retry time exhausted');
            }
            if (options.times_connected > 10) {
                // End reconnecting with built in error
                return undefined;
            }
            // reconnect after
            return Math.max(options.attempt * 100, 3000);
          }
        }
      }
    }
    
    config.development.log4js = {
      appenders: {console: { type: 'console'}},
      categories : {
        "default": { appenders: ['console'], level:'error'},
        "startup": { appenders: ['console'], level:'info'},
        "http": { appenders: ['console'], level:'info'}
      }
    }
    
    config.production = Object.assign({}, config.development);
    module.exports = config;

  • 配置好config.js文件后,终端输入code-push-server启动服务,在浏览器中打开 http://127.0.0.1:3000,登录(用户名: admin 密码: 123456) ,然后获取token
  • 终端输入 code-push login http://127.0.0.1:3000,填入刚刚获取到的token
  • 至此code-push-server配置已经完成

4、向服务器中添加app

code-push app add test-ios ios react-native

code-push app add test-android android react-native


5、项目中配置

  • 集成react-native-code-push到项目中
  • npm install --save react-native-code-push@latest

IOS配置

1、AppDelegate.m配置

#import <CodePush/CodePush.h>
...
  NSURL *jsCodeLocation;
  
    #ifdef DEBUG
        jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
    #else
        jsCodeLocation = [CodePush bundleURL];
        // 如果bundle包名不是默认的main.bundle,需要以下配置
	jsCodeLocation = [CodePush bundleURLForResource:@"bundle/index.ios" withExtension:@"jsbundle"];
    #endif
...

image.png

  • CodePushDeploymentKey值设置为test-ios的Production DeploymentKey值。
  • CodePushServerURL值设置为code-push-server服务地址 http://YOUR_CODE_PUSH_SERVER_IP:3000/ 不在同一台机器的时候,请将YOUR_CODE_PUSH_SERVER_IP改成外网ip或者域名地址。 
  • 将默认版本号1.0改成三位1.0.0

安卓配置 

1、In your android/settings.gradle file, make the following additions at the end of the file:

...
include ':app', ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')

 2、In your android/app/build.gradle file, add the codepush.gradle file as an additional build task definition underneath react.gradle

...
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
...

3、Update the MainApplication.java file to use CodePush via the following changes:

...
// 1. Import the plugin class.
import com.microsoft.codepush.react.CodePush;

public class MainApplication extends Application implements ReactApplication {

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        ...

        @Override
        protected List<ReactPackage> getPackages() {
          ...

          CodePush.getJSBundleFile();
          new CodePush(getResources().getString(com.test.ts.R.string.CodePushDeploymentKey),MainApplication.this,BuildConfig.DEBUG,"http://127.0.0.1:3000");
          return packages;
        }
    };
}

4、Add the Deployment key to android\app\src\main\res\values\strings.xml:

 <resources>
     <string name="app_name">AppName</string>
     <string moduleConfig="true" name="CodePushDeploymentKey">DeploymentKey</string>
 </resources>

React-native

import CodePush from "react-native-code-push";
class App extends Component {
...
componentDidMount() {
  CodePush.allowRestart();
  CodePush.sync(
    { installMode: CodePush.InstallMode.IMMEDIATE, updateDialog: {
      appendReleaseDescription:true,//是否显示更新description,默认为false
      descriptionPrefix:"更新内容:",//更新说明的前缀。 默认是” Description:
      mandatoryContinueButtonLabel:"立即更新",//强制更新的按钮文字,默认为continue
      mandatoryUpdateMessage:"",//- 强制更新时,更新通知. Defaults to “An update is available that must be installed.”.
      optionalIgnoreButtonLabel: '稍后',//非强制更新时,取消按钮文字,默认是ignore
      optionalInstallButtonLabel: '后台更新',//非强制更新时,确认文字. Defaults to “Install”
      optionalUpdateMessage: '有新版本了,是否更新?',//非强制更新时,更新通知. Defaults to “An update is available. Would you like to install it?”.
      title: '更新提示'//要显示的更新通知的标题. Defaults to “Update available”.
    }, },
  );
}
...
App = CodePush(App);

export default App;

6、发布更新

      1、生成资源并发布

  • code-push release-react test-ios ios -d Production (--t <x.x.x针对哪个版本号更新> --m true 是否强更 --des <本次更新说明> --dev <是否测试包,默认false> --plistFile <指定plist路径>)

      2、生成资源再发布

发布更新之前,需要先把 js打包成 bundle,如:

第一步: 在 工程目录里面新增 bundles文件

第二步: 运行命令打包 npx react-native bundle --platform 平台 --entry-file 启动文件 --bundle-output 打包js输出文件 --assets-dest 资源输出目录 --dev 是否调试
eg:
npx react-native bundle --platform android --entry-file index.js --bundle-output ./android/bundles/index.android.bundle --dev false

打包bundle结束后,就可以通过CodePush发布更新了。在终端输入
code-push release <应用名称> <Bundles所在目录> <对应的应用版本> --d: 更新环境 --description: 更新描述 --m: 是否强制更新 
eg:
code-push release GitHubPopular ./android/bundles/index.android.bundle 1.0.6 --d Production --des "支持缓存。" --m true

  • 进入app检查更新

7、版本回滚

code-push rollback <appName> <deploymentName> -r <backVersion>

e.g: code-push rollback MyApp Production -r v1

8、版本清除

code-push deployment clear <appName> <deploymentName>

e.g: code-push deployment clear MyApp Production

9、code-push相关命令(code-push --help)

  • app相关:code-push app --help
  • 添加app:code-push app add <app名称> <platform> react-native
  • 删除app:code-push app rm <app名称>
  • 查看app列表:code-push app ls
  • 版本相关:code-push deployment --help
  • 查看当前版本状态:code-push deployment ls test-ios -k
  • 查看版本更新历史:code-push deployment history test-ios Production
  • 发布相关:code-push release-react --help
  • code-push release-react test-ios ios -d Production (-t <x.x.x针对哪个版本号更新> -m true 是否强更 --des <本次更新说明> --dev <是否测试包,默认false> --plistFile <指定plist路径>)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值