Logo

React Native热部署

avatar yury 08 Aug 2016

序言

React Native在iOS和Android上,JavaScript代码的运行环境都是JavaScriptCore,这也正是支撑Safari的JS引擎。在模拟器上debug的环境则是V8。

顺便提一下,要注意JavaScript Execution Contexts的不同。React Native是一个第三方的JS environment,既不是浏览器也不是Node。在使用React Native的时候,虽然你可以使用NPM,debug的时候后台也跑着已个node server,但是你的代码并不是跑在NodeJS之上。所以不是所有的nodejs的package都可以在RN上用。就像你不能在Chrome和firfox里面用node modules一样。一个典型的例子是jsonwebtoken,这个用到了NodeJS的crypto模块。

communication between JS and OC

原理

下面简要说明一下React Native视图是如何被创建的,这里以iOS为例。

我们需要一个RCTRootView的实例,它可以由RCTBridge初始化:

RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation 
moduleName:@"myapp" initialProperties:nil launchOptions:launchOptions];

RCTRootView是一个UIView,包裹了React Native的view,并提供了native side和the hosted app之间的通信。

这里,jsCodeLocation是关键,它指定了JavaScript code加载的位置。

//Load from development server
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];

//Load from pre-bundled file on disk.
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

//Load from CodePush
jsCodeLocation = [CodePush bundleURL];

在编写业务逻辑的时候,我们会有许多个js文件,打包的时候RN会将这些个js文件打包成一个叫index.ios.bundle(android的是index.android.bundle)的文件,所有的js代码(包括rn源代码、第三方库、业务逻辑的代码)都在这一个文件里,启动App时会第一时间加载bundle文件,所以脚本热更新要做的事情就是替换掉这个bundle文件。

hot_deployment_process.png

因为苹果的开发者协议完全允许执行对JavaScript和assets的over-the-air的更新,所以不必有政策上的担心。

解决方案

国内

react-native-pushy ⭐️236

  1. 官方提供Update Service
    如果要搭建自己的热更新服务,需要编写自己的js模块来与不同的热更新服务器通讯

    你可以单独使用本组件的原生部分(不包括js模块)和命令行工具中的bundle、diff、diffFromIpa、diffFromApk四个功能。
    这些功能都不会使用我们的热更新服务,也无需注册或登录账号。但你可能要编写自己的js模块来与不同的热更新服务器通讯。

    如果您有兴趣使用我们的成果,搭建私有云服务,可以联系我们。

  2. 收费情况

    目前我们的热更新服务完全免费,但限制每个账号不超过3个应用;每个应用不超过10个活跃的包和100个活跃的热更新版本;每个应用每个月不超过10000次下载。iOS和Android版本记
    做不同的应用。已经移除的应用、包版本、热更新版本不在统计之列,所以你可以移除测
    试时产生的和已过期版本来更有效的利用空间。

    我们会在将来推出付费的升级版本,针对用户量较大、版本迭代较快的用户提供扩容方
    案。如果您有急迫的需求,可以联系我们。

  3. 支持崩溃回滚

国外

react-native-code-push ⭐️1345

  1. 官方提供CodePush Service,服务端目前没有开源,不能用自己的服务器
  2. 收费情况:目前免费,无限制
  3. 通过deployment key 可以 take advantage of the Staging and Production deployments, Multi-Deployment Testing
  4. 有History、Rollback功能

react-native-auto-updater ⭐️885

  1. 只能进行全量更新,不是增量更新,只是js更新,不支持assets更新,需要自己配置好服务端

AppHub ⭐️138

  1. 官方提供AppHub Developer Dashboard作后端版本管理,也可以由开发者配置自己的后端
  2. 收费情况:日活用户1000以内免费

总结

  1. react-native-pushy 由reactnative.cn维护,服务器在国内,可以配置自己的服务端,但是并没有看到开源的服务端示例代码。
  2. react-native-auto-updater 不是增量更新,也不支持assets更新。不用第三方服务,要配置自己的服务端。
  3. AppHub收费。
  4. react-native-code-push 由微软维护,文档详尽,功能丰富,缺点是服务器在国外,可能会因为网络问题影响推送的速度和覆盖率,服务端未开源,无法使用自己的服务器。

CodePush使用小结

  • 开始以为CodePush是增量更新,后面使用发现其增量升级仅仅是针对图片资源的,只是对bundle做了zip压缩,通常推送的package大小在600kb左右,还是比较大的。
  • 实际使用中发现有时候存在推送的速度较慢和部分手机始终无法收到推送的问题,CodePush由微软维护,服务器在国外,在国内访问的网速不是很理想。
  • 官方提供CodePush CLI命令行工具
  • 当你第一次创建CodePush app的时候,会自动生成两个deployment key: Staing & Production。利用这两个不同的deployment key,可以进行Multi-Deployment Testing,通过这样,你就不会把未经自己验证的更新推送给终端用户。
  • Multi-Deployment Testing的配置
    • Android
      • app下的build.gradle的buildTypes中,对debug和release分别定义buildConfigField,指定各自的CodePush deployment key
        buildTypes {
            debug {
                buildConfigField "String", "CODEPUSH_KEY", 'YOUR_CODE_PUSH_KEY_FOR_STAGING'
            }
            release {
                signingConfig signingConfigs.release
                minifyEnabled enableProguardInReleaseBuilds
                proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
                buildConfigField "String", "CODEPUSH_KEY", 'YOUR_CODE_PUSH_KEY_FOR_PRODUCTION'
            }
        }
      
      • 在MainActivity中更新CodePush构造方法为new CodePush(BuildConfig.CODEPUSH_KEY, this, BuildConfig.DEBUG);
    • iOS
      • Xcode可以针对不同的”configuration” (e.g. debug, release)定义不同的build settings。
      • Info -> Configuration -> + -> Duplicate "Release" Configuration,重命名为Staging
      • Build Settings -> + -> Add User-Defined Setting,命名为CODEPUSH_KEY,展开,Staging config指定Staging deployment key,Release config指定Production deployment key
      • 打开Info.plist,将CodePushDeploymentKey值设为$(CODEPUSH_KEY)
  • Multi-Deployment Testing的流程通常是这样的:
    • 使用code-push release-react命令推送更新到Staging deployment
    • 运行app的staging/debug build,从server同步更新,验证它是否和预期一致
    • 使用code-push promote命令,将这个通过测试的Staging release promote到Production
    • 运行app的production/release build,从server同步更新,验证它是否和预期一致
  • 通过code-push deployment history <appName> <deploymentName>查看更新推送历史信息,包括版本、描述、更新设备数目与比例等等

参考链接

Tags
react-native
hot-deployment
codepush
联系我们