增量热更新
ReactNative 增量更新
ReactNative 增量更新的内容包含 JS 和图片,在每次应用启动的时候请求服务器更新。
增量更新设计到版本号的管理,版本号存储位置有两个,一个是应用打包的只读目录,另一个是沙盒目录。
版本概念:
基线版本:
App 使用的最新的JS版本。 此 JS 版本号是初始化打包进 App 的,当 Native 代码升级的时候用户需要到市场升级。iOS 可以在 plist 文件加入一个Key 来存储。
当前版本:
JS 在 App 内每次在线更新升级到的版本号。
升级的思路是需要拿着本地的 JS 版本号,向服务器请求最新版本。
本地的 JS 版本号有以下几种状态:
- 第一次发布带有升级程序的 ReactNative 的App,“基线版本”为 0,“当前版本”为null,此时需要用“基线版本”号向服务器发送请求。
- 日常的 JS 升级,以”当前版本“号递增,从服务器获取最新版本。
- 需要发布到市场一次大版本,“当前版本” 例如为2.0,在打包的时候 “基线版本号” 一定是最大的,除非在发布新包的时候忘记升级 ”基线版本“,”基线版本“ 假如为3.0,JS 升级需要拿”基线版本“ 发送请求。为保险起见取 MAX(”基线版本“,"当前版本") 发送请求。
升级原理
JS增量
JS增量包生成使用BSDiff。
安卓和iOS使用BSPatch合并补丁,并导出合并方法给JS调用。
图片增量
图片升级使用git diff 命令找到上版本和当前版本中变化的图片,生成图片增量包。
原理是 ReactNative 会自动找打包命令生成的大 bundle 文件 所在的目录下的图片,所以只要保证我们全量图片和Bundle文件在一起,且严格按照以下的目录放置即可找到。
iOS图片必须有根目录 asset ,下面的图片按照模块文件名划分,asset和 bundle 文件是同级目录。。
安卓图片目录没有asset,四个文件夹 drawable-hdpi,drawable-mdpi,drawable-xhdpi,drawable-xxxhdpi 并列,和bundle文件是同级目录。
增量图片和JS补丁打成一个ZIP文件,下载到对应版本的目录后,首先把上个版本的图片和JS拷贝过来,然后解压,合并JS,覆盖图片。
最终实现的效果是:升级的每个版本都在沙盒中生成一个目录,包含 全量JS 全量图片,如果怕图片过多,可以只保留三个版本,每次升级把旧的版本删除。
回滚:如果升级后,程序启动闪退,且次数过多,需要执行自动回滚,沙盒中保存的历史版本就发挥作用了。只需要把当前版本号更改到上一个版本,让系统找到旧版本的main.jsbundle 就会回滚。
API设计
原生需要暴露给JS使用的类 XSYUpgradeManager
提供方法
- baseVersion 基线版本
- currentVersion 当前版本
- setVersion(version) 设置版本
- versionDesc(source,target) 版本比较,返回bool值
- combine(patchPath,newVersion,callback) bsdiff合并
其他相关类:
- XSYPatchCombine
combineIndexBundle
参数:
patchPath (String) 补丁目录
newVersion (String) 新版本号
completionHandler(combineResult) 合并之后的回调方法
- XSYJSVersion
setVersion 设置当前版本为升级后的版本
参数:
version (String) 新版本号
getBaseVersion 获取基线版本,意为打包时候的当前最新JS版本
getCurrentVersion 获取当前JS版本,用此方法得到的版本号请求服务器最新版本。
versionDesc 比较版本大小,返回BOOL
参数:
source(String)
target(String)
currentVersionBundleURL 获取当前JS版本的bundle路径
参数:
version(String)
JS代码更新
生成增量包
iOS:
react-native bundle --entry-file index.ios.js --bundle-output ./bundle/index.ios.jsbundle --platform ios --assets-dest ./bundle --dev false --minify true
Android:
react-native bundle --entry-file index.android.js --bundle-output ./bundle/index.android.jsbundle --platform android --assets-dest ./bundle --dev false
--entry-file 输入文件
--platform 平台语言
--dev 开发模式
--minify 压缩JS
--bundle-output 输出文件名
注意:如果Xcode直接运行打包,即便设置成--dev 为false
选择Release运行的时候Xcode 会自动执行此命令。
图片更新
1.服务器生成增量包
2.手机端下载增量包
3.手机端拷贝上版本所有图片到新版本目录
4.手机端合并增量图片为全量图片