codepush支持多bundle更新重构

codepush实现原理

code-push.png

梳理下关键节点

  • 前端获取serverURL、appVersion、deploymentKey
  • 请求serverURL查询deploymentKey对应的包是否需要更新,appVersion作为匹配条件(后续灰度发布可自行增加其他条件)
  • 服务端返回downloadUrl、packageHash(一组唯一迭代hash值,类似versionCode或者build号)
  • 请求downloadUrl下载最新bundle包,通过packageHash作为路径标识存放到本地
  • 加载bundle的时候检查是否存在更新包,获取缓存的packageHash并加载bundle包
  • 如最新bundle包出现异常,自动回滚到上一版...

原生与RN混合开发codepush存在的问题

  • deploymentKey作为静态变量保存,如果切换到别的页面,为了获取正确的bundle资源,需要再次设置对应资源的deploymentKey,原先的deploymentKey将会被覆盖,那么原先加载完成的数据将会面对资源不一致的问题,无法正确更新;
  • codepush下载事务机制是每次只下载一个任务,如该任务已经存在,将不会继续检查更新下载;然而,混合开发的情况下,前一个下载任务正在执行,如果切换到别的页面,加载另一个不相关的bundle,也不会进行数据更新检查,将会浪费更新机会;

重构方案

基于以上存在的问题,要对现有的codepush结构进行调整,首先就是要支持多个不同bundle同时更新,需要业务层自行传入关键字来区分需要更新哪个bundle;再者对codepush更新后的bundle存放路径需要进行关键字分组,方便按组清理和回滚;

  • js端对现有结构改造,传入bundle名,调用方法:
CodePush({ bundle: "bundleName" });
  • deploymentKey和bundleName做一组映射,js向原生传递bundleName,原生自行转换成deploymentKey,映射由外部转换完传入,然后将deploymentKey回传给js进行更新检查,改造方法(android雷同):
//由业务测根据配置项返回deploymentKey
- (NSString *)getDeploymentKey:(NSString *)bundleName;
  • 改造更新完的bundle存放路径规则,将原有路径: ./CodePush/{packageHash}/{file}添加一个deploymentKey分组,改为:./CodePush/{deploymentKey}/{packageHash}/{file},如需要清理或回滚,可通过deploymentKey关键字查找路径,全部清理或回滚到上一版packageHash包体(android雷同)
+ (NSString *)getPackageFolderPath:(NSString *)deploymentKey packageHash:(NSString *)packageHash
{
    return [[self getDeploymentFilePath:deploymentKey] stringByAppendingPathComponent:packageHash];
}
+ (NSString *)getDeploymentFilePath:(NSString *)deploymentKey
{
    return [[self getCodePushPath] stringByAppendingPathComponent:deploymentKey];;
}

当然,codepush重构的改造量还是比较多的,这些属于冰山一角,获取deploymentKey几乎贯穿整个事务;js初始的时候只传入bundleName,同名bundleName在不同的工程项目中配置的deploymentKey是不同的,需要原生业务代码提供;不同deploymentKey也需要独立缓存最新包信息,便于更新后获取并加载等等;

feature

  • codepush私有服务改造
  • 白名单发布、灰度发布(设置多种更新条件)
  • 更新后监控数据回传

你可能感兴趣的:(codepush支持多bundle更新重构)