CodePush停服后,如何用腾讯Shiply快速实现ReactNative热更新?

825 阅读5分钟

1.  背景

CodePush是微软VisualStudioAppCenter服务的一个子功能,支持动态下发RN热更新产物。

但是VisualStudioAppCenter 2025/3/31 已经停止服务,如果想继续使用CodePush需要自己独立部署。

专门独立部署一套后台服务,对于个人开发者尤其是客户端开发来说时间成本较高,后期维护也需要投入不少精力,最好还是使用已有的下发平台。

调研了一下发现目前Pushy和Shiply平台都支持RN热更新。

Pushy 是ReactNative中文网推出的RN下发平台,支持差量更新,CLI和网页双端管理。

Shiply 是腾讯端服务团队推出的面向客户端的全场景发布平台,支持动态下发配置、资源、软件包(App)、Android热更新、flutter热更新,最近刚上线了RN热更新功能。

 

体验下来感觉Shiply的前端交互更友好,有完整的审批发布流程,支持多维度的下发规则,能看到客户端下发加载数据,下面详细介绍下Shiply RN热更新的接入和使用过程。

 

2.  Shiply RN热更新接入实战

2.1.  创建Shiply项目及产品

参考第三点中的发布平台使用指引,创建一个测试项目,并创建Android和iOS产品。

2.2.  创建RN模块

参考第三点中的发布平台使用指引,创建一个名叫「testRN」的模块,绑定2.1中创建的两个产品。

2.3.  接入Shiply RN动态化SDK

2.3.1.  创建RN demo

先创建一个RN demo工程:

npx @react-native-community/cli init TestShiplyRN --version 0.78

 

2.3.2.  添加RN层依赖

在demo项目根目录执行

npm install rn-shiply-upgrade

 

2.3.3.  添加Android层依赖

在项目Android目录下的build.gradle文件中添加maven地址

allprojects {
  repositories {
    maven { url "https://tencent-tds-maven.pkg.coding.net/repository/shiply/repo" }
  }
}

 

2.3.4.  添加热更新检查与加载代码

2.3.4.1.  修改RN层代码
 
import React from 'react';
import {Platform, Text, View} from 'react-native';
 
import { HotUpdateHelper, HotUpdateButton } from 'rn-shiply-upgrade'; // 新增导入辅助类
 
const App = () => {
    // 初始化热更新配置(只需一次)
    HotUpdateHelper.getInstance({
        // 需要修改为业务方自己的android/ios appId和appKey
        appId: Platform.OS === 'ios' ? 'iOSAppId' : 'androidAppId',
        appKey: Platform.OS === 'ios'
            ? 'iOSAppKey'
            : 'androidAppKey',
        deviceId: '33333', // 需要修改为实际的设备id
        appVersion: "1.0.0", // 应用版本号
        shiplyResName: 'testRN', // 资源key名称,对应shiply平台上中创建的RN模块名字
    });
 
    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <Text> 热更新测试: 当前是本地内容</Text>
            <View style={{ height: 10 }} />
            {/* 默认样式按钮 */}
            <HotUpdateButton />
        </View>
            );
};
 
export default App;
 

androidAppId/androidAppKey/iOSAppId/iOSAppKey要改成2.1中创建的Android/iOS产品的真实appId/appKey。

 

 

2.3.4.2.  修改Android层代码
class MainApplication : Application(), ReactApplication {
 
  override val reactNativeHost: ReactNativeHost =
      object : DefaultReactNativeHost(this) {
        override fun getPackages(): List<ReactPackage> =
            PackageList(this).packages.apply {
              // Packages that cannot be autolinked yet can be added manually here, for example:
              // add(MyReactNativePackage())
            }
 
        override fun getJSMainModuleName(): String = "index"
 
        override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
 
        override fun getJSBundleFile(): String? {
              var result: String? = null
              // 从shiply获取RN bundle路径,业务方需要将资源key修改为shiply平台中创建的资源key名称
              result = ShiplyReactNativeUpgradeModule.getJSBundleFilePath(applicationContext as Application, "testRN")
              Log.d("MainApplication", "getJSBundleFile: $result")
              return result
        }
 
        override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
        override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
      }
 
  override val reactHost: ReactHost
    get() = getDefaultReactHost(applicationContext, reactNativeHost)
 
  override fun onCreate() {
    super.onCreate()
    SoLoader.init(this, OpenSourceMergedSoMapping)
    if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
      // If you opted-in for the New Architecture, we load the native entry point for this app.
      load()
    }
  }
}

复写getJSBundleFile方法,从shiply获取bundle路径。

2.3.4.3.  修改iOS层代码
class AppDelegate: RCTAppDelegate {
  override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    self.moduleName = "TestShiplyRN"
    self.dependencyProvider = RCTAppDependencyProvider()
 
    // You can add your custom initial props in the dictionary below.
    // They will be passed down to the ViewController used by React Native.
    self.initialProps = [:]
 
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
 
  override func sourceURL(for bridge: RCTBridge) -> URL? {
    self.bundleURL()
  }
 
  override func bundleURL() -> URL? {
 
    // 业务方需要将资源key修改为shiply平台中创建的资源key名称
    ShiplyReactNativeUpgradeUtil.getJSBundleFilePath("testRN");
    if let path = ShiplyReactNativeUpgradeUtil.getJSBundleFilePath("testRN") {
        NSLog("bundleURL called,path = %@ ", path);
        return URL(fileURLWithPath: path)
    }
    return Bundle.main.url(forResource: "main", withExtension: "jsbundle")
  }
}

复写bundleURL方法,从shiply获取bundle路径。

 

做完以上步骤后就完成了接入。

 

这时点击检查更新没有什么效果,因为还没有在shiply配置新版本RN热更新产物。

2.4.  打包RN动态化产物

 

2.4.1.  修改Demo测试代码

 
import React from 'react';
import {Platform, Text, View} from 'react-native';
 
import { HotUpdateHelper, HotUpdateButton } from 'rn-shiply-upgrade'; // 新增导入辅助类
 
const App = () => {
    // 初始化热更新配置(只需一次)
    HotUpdateHelper.getInstance({
        // 需要修改为业务方自己的android/ios appId和appKey
        appId: Platform.OS === 'ios' ? 'iOSAppId' : 'androidAppId',
        appKey: Platform.OS === 'ios'
            ? 'iOSAppKey'
            : 'androidAppKey',
        deviceId: '33333', // 需要修改为实际的设备id
        appVersion: "1.0.0", // 应用版本号
        shiplyResName: 'testRN', // 资源key名称,对应shiply平台上中创建的RN模块名字
    });
 
    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            {/*<Text> 热更新测试: 当前是本地内容</Text>*/}
            <Text> 热更新测试: 当前是热更新内容</Text>
            <View style={{ height: 10 }} />
            {/* 默认样式按钮 */}
            <HotUpdateButton />
        </View>
            );
};
 
export default App;
 

主要修改下UI文案,区分本地版本和热更新版本。

2.4.2.  打包Android产物

在工程的根目录输入如下命令进行打包:

react-native bundle --entry-file ./index.js --bundle-output ./bundle/androidBundle/index.android.bundle --platform android --assets-dest ./bundle/androidBundle --dev false 

执行后,工程根目录/bundle/androidBundle下会生成Android产物,全选androidBundle下所有文件后进行压缩,得到的zip文件将用于上传到shiply。

 

2.4.3.  打包iOS产物

在工程的根目录输入如下命令进行打包:

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

执行后,工程根目录/bundle/iOSBundle下会生成iOS产物,全选iOSBundle下所有文件后进行压缩,得到的zip文件将用于上传到shiply。

 

 

2.5.  发布RN动态化产物

参考3中的发布平台使用指引,上传2.4中的zip文件生成发布任务:

 

 

还原测试代码,在Demo Android目录执行./gradlew app:assembleRelease编译release apk,安装后运行九能拉到远端的RN产物了。

这里按钮和弹框都是shiply sdk提供的默认UI,也可以参考SDK中的HotUpdateButton 和HotUpdateHelper来自定义UI和请求时机。

 

安装加载成功后,shiply前端页面可以看到相关的数据上报。

 

2.6.  小结

总体体验下来接入比较顺畅,花个半天时间就能正常接入shiply rn热更新。因为CodePush下架急需替代方案来实现RN动态化的开发者可以考虑接入试用下。

掘金图片上传一直失败,也可以看下这篇文章:blog.csdn.net/sckgenius/a…

3.  参考文档

 

Shiply ReactNative 动态化 SDK 接入指引 | Shiply 专业版

ReactNative 动态化发布平台使用指引 | Shiply 专业版