react-native热更新-code-push-server

2,262 阅读5分钟

本文由我们团队的丁武龙组内分享总结

一、相关知识

什么是code-push-server

code-push-server是基于node.js+mysql搭建自己的热更新服务器,

什么是CodePush

CodePush是微软开发的一个云服务器,通过它,开发者可以直接在用户的设备上部署手机应用更新。CodePush相当于一个中心仓库,开发者可以推送当前的更新(包括JS/HTML/CSS/IMAGE等)到CoduPush,然后应用将会查询是否有更新,由于codePush服务器在国外,国内使用的话速度并不是很快,所以就准备自建CodePush服务器

RN热更新工作原理

在自建CodePush服务器的之前,首先要了解的是RN热更新他的工作原理如下图

二、server端初始化

1.安装code-push-server

在安装code-push-server之前,先安装以下几个依赖

安装 react-native-cli react-native命令行工具,安装后可以在终端使用react-native命令
npm i -g  react-native-cli
安装code-push-cli 连接微软云端,管理发布更新版本命令行工具,安装后可以在终端使用code-push命令
npm i -g code-push-cli
安装react-native-code-push 集成到react-native项目
yarn add react-native-code-push
react-native link react-native-code-push
安装code-push-server

文档提供了两种安装code-push-server的方式

  • 使用npm安装

    npm install code-push-server -g

  • 手动安装(官方推荐),因为code-push-server可能需要自己配置修改,所以建议手动安装

    git clone https://github.com/lisong/code-push-server
    npm install
    

2.安装mysql并启动

直接去官网下载按照步骤一步一步安装即可

3.初始化mysql数据库

终端输入:

code-push-server-db init --dbhost localhost --dbuser root --dbpassword

初始化数据库遇到的坑

1.初始化时提示

原因:没有输入数据库密码,只需要在终端输入

code-push-server-db init --dbhost localhost --dbuser root --dbpassword ‘你的数据库密码’

2.提示数据库表已存在

解决办法:重新创建一个表,终端输入:

  code-push-server-db init --dbname '表名' --dbhost localhost --dbuser root --dbpassword '密码'

出现提示更新数据库问题:

终端执行:bin/db upgrade --dbhost localhost --dbuser root --dbpassword '密码'

如果还行不通,那就只有删掉数据库重新走一遍了

三、server端修改config.js配置并启动服务

首先找到code-push-server文件夹下面的config.js文件,我的路径/usr/local/lib/node_modules/code-push-server/config/config.js,修改配置如下


 db: {
   username: "root",
   password: "12345678",
   database: "codepush",
   host: "127.0.0.1",
   dialect: "mysql"
 },
 //文件存储在本地配置 当storageType为local时需要配置
 local: {
   storageDir: "/Users/lizhao/Desktop/hotUpdateDemo/workspace/storage",
   //文件下载地址 CodePush Server 地址 + '/download' download对应app.js里面的地址
   downloadUrl: "http://localhost:3000/download"
 },
 jwt: {
   // 登录jwt签名密钥,必须更改,否则有安全隐患,可以使用随机生成的字符串
   // Recommended: 63 random alpha-numeric characters
   // Generate using: https://www.grc.com/passwords.htm
   tokenSecret: 'INSERT_RANDOM_TOKEN_KEY'
 },
 common: {
   dataDir: "/Users/lizhao/Desktop/hotUpdateDemo/workspace/storage",
   //选择存储类型,目前支持local和qiniu配置
   storageType: "local"
 },

配置好了之后,就开始启动服务器吧,在终端输入

./bin/www

如果没有报错的话,那就说明启动成功

到了这里,code-push-server服务端已经配置好了

三、客户端集成

1.创建服务端应用

基于code-push-server服务

终端输入

  code-push login http://127.0.0.1:3000 #浏览器中登录获取token复制到终端 账号admin 密码123456
  code-push app add AppDemo ios react-native #创建ios版本App,获取Production DeploymentKey并        记录下来

登录可能出现的问题

  • 在终端输入code-push login的时候,如果出现[Error] You are already logged in from this machine.的时候,在终端试着输入命令:code push logout,如果出现[Error] connect ECONNREFUSED 127.0.0.1:3000错误,可以直接删除 ~/.code-push.config文件

2.配置iOS工程

1.打开info.plist , 添加CodePushDeploymentKey 和CodePushServerURL

1.CodePushDeploymentKey值为AppDemo的DeploymentKey

2.CodePushServerURL 值设置为code-push-server服务器地址,模拟器调试时候设置为 http://127.0.0.1:3000/ 真机模式下,请设置为外网ip或者域名地址

修改AppDelegate.m

因为前面已经link过了react-native-code-push,所以不需要手动链接,在Appdelegate.m文件里,修改以下代码

  #import "AppDelegate.h"
  #import <CodePush/CodePush.h>

  #import <React/RCTBundleURLProvider.h>
  #import <React/RCTRootView.h>


  ...
  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  {
    NSURL *jsCodeLocation;

      #ifdef DEBUG
          jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
      #else
          jsCodeLocation = [CodePush bundleURL];
      #endif
    NSLog(@"jsCodeLocation == %@",jsCodeLocation);
    RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                        moduleName:@"hotUpdateDemo"
                                                 initialProperties:nil
                                                     launchOptions:launchOptions];
    rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    UIViewController *rootViewController = [UIViewController new];
    rootViewController.view = rootView;
    self.window.rootViewController = rootViewController;
    [self.window makeKeyAndVisible];
    return YES;
  }
  ...

3.添加更新检查

1.引入react-native-code-push
  import CodePush from "react-native-code-push"

在App.js入口componentDidMount方法添加

  componentDidMount() {
      CodePush.sync({

          //在更新配置中通过指定installMode来决定安装完成的重启时机 总共有三种,分别是               ON_NEXT_RESUME(装完成后会在应用进入后台后重启更新)、ON_NEXT_RESTART(安装完成后会在下次重启后进行更新)、IMMEDIATE(表示安装完成立即重启更新)
          installMode: CodePush.InstallMode.IMMEDIATE,     
          updateDialog: true   //是否显示更新弹窗
      });
  }
2.发布更新

发布更新之前,需要先将js包打包成bundle,终端输入

  react-native bundle --platform ios --dev false --entry-file index.js --bundle-output   
  ios/main.jsbundle   #运行该命令打包bundle文件

打包bundle完成之后,就可以通过codePush发布更新了,在终端输入

  code-push release-react HotApp ios -d Staging   #默认是打包Staging环境的,正式环境打包方式如下
  code-push release-react HotApp ios -d Production #打包正式环境

  ------mandatory #表示是否强制更新
  ------description #应用更新描述