Linux上搭建热更服务器并在移动端通过react native项目验证


本文介绍搭建热更服务器并在手机上测试react native热更的全过程。
简书地址

安装MySQL

安装完成后,会弹出初始密码,粗细的我,随手点了OK,此处挖坑半天。
权限密码问题可以参考这篇博客,其它的都是小问题

app热更原理.png

code-push热更服务器搭建:

安装code-push-server

  • npm安装
# 安装code-push-server
npm install code-push-server -g
  • 源码安装(推荐)
# 从git库下载最新代码
git clone https://github.com/lisong/code-push-server.git
# 进入到code-push-server目录
cd code-push-server
# 安装
npm install

Code-Push-Server配置

修改config/config.js文件,指定数据库,数据存放位置

  • 配置数据库
    db: {
    username: "root",
    password: "Your PWD",
    database: "codepush",
    host: "127.0.0.1",
    port: 3306,
    dialect: "mysql"
    }
    
  • 配置存储(默认为local,本次也采用local)
common: {
   // dataDir用于进行存放比对文件
   dataDir: "/Users/tablee/workspaces/data",
   // 存储类型,可选值有local,oss,qiniu,s3
   storageType: "local"
},

// 文件存储在本地 当storageType为local时需要配置
local: {
   // 二进制文件存放目录,文件下载目录,不要使用临时目录
   storageDir: "/Users/tablee/workspaces/storage",
   // 文件下载地址 CodePushServer地址 + ’/download‘,download对应app.js里面的地址
   //默认此处的下载地址是127.0.0.1:3000这个自然是错误的,要外网ip地址
   downloadUrl: "https://tech.haier.net:7788/download",
   // public static download spacename
   public: '/download'
},


//七牛云存储配置 当storageType为qiniu时需要配置
qiniu: {
  accessKey: "",
  secretKey: "",
  bucketName: "",
  //文件下载域名地址
  downloadUrl: ""
},
//阿里云存储配置 当storageType为oss时需要配置
oss: {
  accessKeyId: "",
  secretAccessKey: "",
  endpoint: "",
  bucketName: "",
  // 对象Key的前缀,允许放到子文件夹里面
  prefix: "", 
  // 文件下载域名地址,需要包含前缀
  downloadUrl: "",
}
  • 配置签名,可以不修改,但是推荐更改
    jwt: {
      // 登录jwt签名密钥,必须更改,否则有安全隐患,可以使用随机生成的字符串
      // Recommended: 63 random alpha-numeric characters
      // Generate using: https://www.grc.com/passwords.htm
      tokenSecret: 'https://www.grc.com/passwords.htm'
    }
    

    初始化数据库

    配置完成后,进行数据初始化工作
  • npm安装
    # 初始化数据库,**替换为数据库密码**(参考后面配置说明)
    code-push-server-db init --dbhost localhost --dbuser root --dbpassword **Your PWD** --dbport 3306
    
  • 源码安装
    # 初始化数据库
    ./bin/db init --dbhost localhost --dbuser root --dbpassword **Your PWD** --dbport 3306
    
  • *注意事项**:
  1. 不论采取哪种安装方式,初始化数据库时要保证数据库用户名密码正确;数据库中不能存在codepush数据库(默认数据库为codepush)
  2. 采用源码安装,执行bin目录下的db命令时,要保证此文件具有可执行权限,如果没有,需要添加权限
    # 添加db文件的可执行权限
    chmod +x bin/db
    
  3. 如果数据库密码复杂,带有特殊符号,初始化语句将执行失败。此时因为是第一次安装,可以在数据库服务器手动创建名为**codepush**(必须是这个名字)的数据库,然后执行/opt/chuangke/code-push-server/sql/目录下的codepush-all.sql脚本来初始化数据库。
    初始化成功后数据库中的表如下:
    codepush database

    服务启动

    安装配置文件中的目录结构,到/Users目录中建立如下文件夹 /Users/tablee/workspaces/storage
  • npm启动
# 启动服务,默认使用3000端口,可以在浏览器中打开 http://127.0.0.1:3000
code-push-server

# 指定端口号运行
PORT=3000 HOST=127.0.0.1 NODE_ENV=production code-push-server
  • 源码启动
# 启动服务(保证www具有可执行权限),在浏览器中打开 http://127.0.0.1:3000
./bin/www

# 以守护进程的方式运行
nohup ./bin/www &

# 指定端口号运行
PORT=3000 HOST=127.0.0.1 NODE_ENV=production node ./bin/www
  • forever 后台启动(推荐)
  • 先安装forever*
    当然,有人说forever已经过时了,推荐使用pm2代替forever,请参考linux npm start 保持后台运行
    # 全局安装
    $ npm install forever -g
    # 查看是否安装成功
    $ forever list
    info:    No forever processes running
    
    很抱歉,如果不顺利的话,会有这么个情况
[root@izm5e3m6sxwr4dw9w7r6h4z lib]# npm install forever -g
/opt/software/node-v10.0.0-linux-x64/bin/forever -> /opt/software/node-v10.0.0-linux-x64/lib/node_modules/forever/bin/forever
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.7 (node_modules/forever/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.7: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

+ forever@0.15.3
updated 1 package in 2.109s
[root@izm5e3m6sxwr4dw9w7r6h4z lib]# forever list
-bash: forever: 未找到命令
[root@izm5e3m6sxwr4dw9w7r6h4z lib]# 

不美丽了,命名安装成功了,但是还是提示找不到命令,怎么办呢?我来教你,这个是因为这个-g是吧命令安装到了node所在目录,可以看看具体在哪

[root@izm5e3m6sxwr4dw9w7r6h4z ~]# npm list -g --depth 0
/opt/software/node-v10.0.0-linux-x64/lib
├── forever@0.15.3
└── npm@5.6.0

[root@izm5e3m6sxwr4dw9w7r6h4z ~]# cd /opt/software/node-v10.0.0-linux-x64/lib
[root@izm5e3m6sxwr4dw9w7r6h4z lib]# ls
node_modules
[root@izm5e3m6sxwr4dw9w7r6h4z lib]# cd node_modules/forever/bin/
[root@izm5e3m6sxwr4dw9w7r6h4z bin]# ls
forever  monitor
[root@izm5e3m6sxwr4dw9w7r6h4z bin]#

这次是真的看见forever被安装到哪里,接下来就来个软链到/usr/bin下就可以了

[root@izm5e3m6sxwr4dw9w7r6h4z bin]# ln -s /opt/software/node-v10.0.0-linux-x64/lib/node_modules/forever/bin/forever /usr/bin/forever
[root@izm5e3m6sxwr4dw9w7r6h4z bin]# forever list
info:    No forever processes running
[root@izm5e3m6sxwr4dw9w7r6h4z bin]#

完美,接着使用forever启动应用啦。
比如我的server源码的位置在/opt/chuangke/code-push-server/,在当前目录下执行如下命令启动

NODE_ENV=production forever start -l log/forever.log -o log/info.log -e log/err.log bin/www

可以用如下绝对路径命令启动:

NODE_ENV=production forever start -l /opt/chuangke/code-push-server/log/forever.log -o /home/haieradmin/codepush/code-push-server/log/info.log -e /home/haieradmin/codepush/code-push-server/log/err.log /home/haieradmin/codepush/code-push-server/bin/www
  • 服务启动验证
    命令行验证
$ forever list
info:    Forever processes running
data:        uid  command                   script                                 forever pid   id logfile                                        uptime        
data:    [0] 8Or8 /usr/local/node8/bin/node /opt/chuangke/code-push-server/bin/www 60199   60209    /opt/chuangke/code-push-server/log/forever.log 0:15:2:21.503 

如果服务器启动成功,则用浏览器访问默认的3000端口,可以看到如下效果
首页
到此服务器端到配置就完成了。

客户端热更验证

客户端测试代码以 https://github.com/lisong/code-push-demo-app 为例

客户端安装code-push-cli

# 全局安装
$ npm install -g code-push-cli 
# 查看版本
$ code-push -v
2.1.8

下载客户端验证程序,并安装第一版

  1. clone程序并install
$ git clone git@github.com:lisong/code-push-demo-app.git
#  cd  到demo路径,执行npm install 安装node依赖包
$ cd code-push-demo-app
$ npm install

打开命令终端,登录code-push-server服务器,这里配置为local,所以登录地址为http://127.0.0.1:3000

$ code-push login http://127.0.0.1:3000  //账号密码为博主提供  account:  admin password:  123456
登录成功之后获取token

将文本框中的key复制粘贴到登录终端,点击回车登录成功
登录页面
输入账号密码,点击登录。获取token:
获取token

$ code-push login http://127.0.0.1:3000
Please login to Mobile Center in the browser window we've just opened.
Enter your token from the browser:  HugyOJpzvzhEhB05galUftoL4zrz4ksvOXqog
Successfully logged-in. Your session file was written to C:\Users\marvin\AppData\Local\.code-push.config. You can run the code-push logout command at any time to delete this file and terminate your session.

在命令行查看当前热更服务器的部署信息,

$ code-push app list
┌──────┬─────────────┐
│ Name │ Deployments │
└──────┴─────────────┘
  1. 添加新的APP(以安卓为例)
    # 安卓版
    $ code-push app add CodePushReactNativeDemo-android android react-native
    Successfully added the "CodePushReactNativeDemo-android" app, along with the following default deployments:
    ┌────────────┬───────────────────────────────────────┐
    │ Name       │ Deployment Key                        │
    ├────────────┼───────────────────────────────────────┤
    │ Production │ VKNbn9Oe5Wj9bPoGkYCUVuzRuqHV4ksvOXqog │
    ├────────────┼───────────────────────────────────────┤
    │ Staging    │ 6KfLoVvhgdsnFzFCIohRb2t5grmD4ksvOXqog │
    └────────────┴───────────────────────────────────────┘
    # 再运行命令查看
    $ code-push app list
    ┌─────────────────────────────────┬─────────────────────┐
    │ Name                            │ Deployments         │
    ├─────────────────────────────────┼─────────────────────┤
    │ CodePushReactNativeDemo-android │ Production, Staging │
    └─────────────────────────────────┴─────────────────────┘
    
  2. 修改配置
    添加完成之后可以用code-push app list命令查看创建好的app,并将测试的Staging key拷贝到MainApplication.java中的 “Your Key“ 的位置,推送的时候通过key将app和服务器端关联。

用Android Studio打开code-push-demo-app/android目录到MainApplication.java里面修改以下代码:

@Override

protected List<ReactPackage> getPackages() &#123;

  return Arrays.<ReactPackage>asList(

      new MainReactPackage(),

      new CodePush(

         "YourKey",  // code-push app add项目后生成的app 推送key

         MainApplication.this,

         BuildConfig.DEBUG,

         "YourCodePushServerUrl"   // config.js中配置的downloadUrl 地址 不需要/download后缀

      )
  );
&#125;

我的配置是:
修改MainApplication.java的代码如下:

    @Override
    protected List<ReactPackage> getPackages() &#123;
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          new CodePushBuilder(getResources().getString(R.string.reactNativeCodePush_androidDeploymentKey),getApplicationContext())
                .setIsDebugMode(BuildConfig.DEBUG)
                .setServerUrl(getResources().getString(R.string.reactNativeCodePush_androidServerURL))
                .build()
      );
    &#125;

修改android/app/src/main/res/values/strings.xml文件,指定reactNativeCodePush_androidDeploymentKey和reactNativeCodePush_androidServerURL的值。

<resources>
    <string moduleConfig="true" name="reactNativeCodePush_androidDeploymentKey">6KfLoVvhgdsnFzFCIohRb2t5grmD4ksvOXqog</string>
    <string moduleConfig="true" name="reactNativeCodePush_androidServerURL">http://xxx.xxx:3000/</string>
    <string name="app_name">CodePushDemoApp</string>
</resources>
  1. cd 到code-push-demo-app目录,允许react-native start 启动react-native 服务。可以选择用数据线连接手机,手机开启开发者模式。也可以直接将code-push-demo-app\android\app\build\outputs\apk\debug以后的apk包发送到手机上,直接打开安装。

    $ react-native run-android
    

    在手机上运行app的截图如下:
    code-push-demo-app

  2. Android Studio编译并将项目运行到手机上,reload更新到最新js包在code-push-demo-app中首页随意做一些修改,这里是将CodePushDemoApp/App.js文件做了如下修改。
    一些修改
    执行推送命令

# 测试环境执行:
$ code-push release-react CodePushReactNativeDemo-android android
Detecting android app version:

Using the target binary version value "2.1.0" from "android\app\build.gradle".

Running "react-native bundle" command:

node node_modules\react-native\local-cli\cli.js bundle --assets-dest C:\Users\marvin\AppData\Local\Temp\CodePush\CodePush --bundle-output C:\Users\marvin\AppData\Local\Temp\CodePush\CodePush\index.android.bundle --dev false --entry-file index.js --platform android
Scanning folders for symlinks in D:\Git\oschina\react\code-push-demo-app\node_modules (101ms)
Scanning folders for symlinks in D:\Git\oschina\react\code-push-demo-app\node_modules (48ms)
Loading dependency graph, done.
bundle: Writing bundle output to: C:\Users\marvin\AppData\Local\Temp\CodePush\CodePush\index.android.bundle
bundle: Done writing bundle output
bundle: Copying 1 asset files
bundle: Done copying assets

Releasing update contents to CodePush:


Successfully released an update containing the "C:\Users\marvin\AppData\Local\Temp\CodePush\CodePush" directory to the "Staging" deployment of the "CodePushReactNativeDemo-android" app.

# 生产环境执行:
$ code-push release-react CodePushReactNativeDemo-android android -d Production

#指定版本,添加注释
$ code-push release-react CodePushReactNativeDemo-android android -d Production --des "marvin code push testing" -t "1.0.0"

Successfully 表示热更包推送成功,然后在手机上点击Press for dialog-driven sync链接。
弹出下载确认
确认更新

点击【install】
已更新
至此,热更服务器搭建,及android版app体验完毕。

扩展

1、产看更新包安装情况

# code-push deployment history appName deploymentName
code-push deployment history CodePushReactNativeDemo-android Staging

Staging 或者 Production
code push Staging

2、列表部署名称

code-push deployment ls CodePushReactNativeDemo-android

部署名

3、常见错误
3.1、 download地址写错,默认是http://127.0.0.1:3000 如果不改成外网域名和端口,下载将失败。
app启动抓包查看的结果就是,返回的下载地址无法下载到资源。
下载地址错误

3.2、nginx限制资源大小
需要修改配置,我们的一个app打包后约70M,上传时就报错了,后来才知道是nginx指定的上传大小是50M,所以要修改nginx配置文件,加上client_max_body_size 100M; 这个样配置。

3.3、数据库配置错误
将数据库的端口,或者用户名密码写错也很常见

3.4、目录权限问题
配置文件里默认的dataDir和storeage目录必须有code-push运行用户的操作权限,否则会有以下错误。
目录权限问题

常用命令

// 账户相关
code-push login 登陆
code-push loout 注销
code-push access-key ls 列出登陆的token
code-push access-key rm  删除某个 access-key
// app操作相关
code-push app add   react-native  在账号里面添加一个新的app
code-push app remove 或者 rm 在账号里移除一个 app
code-push app rename 重命名一个存在 app
code-push app list 或则 ls 列出账号下面的所有 app
code-push app transfer 把app的所有权转移到另外一个账号
// 应用信息相关
code-push deployment add  部署
code-push deployment rm  删除部署
code-push deployment rename  重命名
code-push deployment ls  列出应用的部署情况
code-push deployment ls  -k 查看部署的key
code-push deployment history   查看历史版本
// 发布
code-push release-react   -t 版本  -d 环境  --des 描述 -m true (强制更新)

// 清除历史部署记录
code-push deployment clear  Production or Staging

// 回滚
code-push rollback  Production --targetRelease v4(codepush服务部署的版本号)

注意事项:

  1. 更新规则
    1> CodePush部署版本 > App版本

    更新可用,但当前版本比运行版本高。不作更新

    2> CodePush部署版本 < App版本

    不执行更新处理

    3> CodePush部署版本 == App版本

    自动下载更新,并根据加载策略加载最新bundle

  1. 回滚

    当部署的版本不同时,不能跨版本回滚。

    例如:CodePush历史版本中为2.10.1,此时发布2.10.2版本。当从2.10.2发起回滚操作回到2.10.1时,是不可行的。

部署信息参数

在部署了版本之后,执行 【code-push deployment ls uniApp-Android】可以查看当前版本、当前部署环境下的部署信息:

  1. Update Metadata(更新信息)
    Label:标识当前部署版本,每部署新版本,版本号增加1

    App Version:当前部署的App版本号

    Mandatory:是否强制更新

    Release Time:部署时间

    Released By:部署用户

    Description:部署 描述信息

从上面内容不难发现,这些信息基本都会在我们执行 code-push release 时配置

  1. Install Metrics(安装指标)

    Active:成功安装并运行当前release的用户的数量,即表示当前下载更新部署的活跃用户数量,of 左边数会随着用户安装、卸载而 增加、减少。of右边数代表当前安装或收 到部署版本的用户数,当有用户卸载App,该数值会降低。

    因此它很好的解释了当前更新包有多少活跃用户,多少用户接收过这个安装包

    Total:成功安装部署当前release的用户量,只增不减

    Pending:当前release版本被下载的数量,但是还没有被安装,该值会随着用户下载安装后增加, 在卸载时降低。

参考资料

code-push-server 搭建自己的推送服务器流程
热更新(android)windows系统code-push-server 的使用
ReactNative集成CodePush教程 集成Code Push的案例说明
react-native热更新全方位讲解
零客户端开发经验 React Native 热更新 CodePush 打包集成指北
react native codepush热更新解决成功更新
Android Studio 权威教程 打包、生成jks密钥、签名Apk、多渠道打包
http://www.tl628.com/index.php/2018/05/31/code-push_fa_bu_de_shi_hou_chu_xian_error_upload_error/


评论
  目录