React Native学习<五> React Native 详细实现热部署、增量差异化热更新

原文地址 http://www.lcode.org/react-native-hot-update/

本文来自Songlcy投稿:文章地址:http://blog.csdn.net/u013718120/article/details/55096393
本篇博客是React Native中比较经典的内容:热更新部署。

一、前言

Android原生App中我们实现热修复有很多种选择:Tinker、hotFix、Qzone的热更新等等。基本的思路都是大同小异的。React Native中的热更新有点像App的版本更新,也就是根据查询server端的版本和手机端目前App的版本进行对比,然后来执行是否更新的操作。根本原因在于React Native的加载启动机制:React Native会将一系列资源打包成js bundle文件,系统加载js bundle文件,解析并渲染。所以,React Native热更新的根本原理就是更换js bundle文件,并重新加载,新的内容就完美的展示出来了。微软为我们提供了CodePush来简化热更新的操作,但是由于速度等原因在国内并没有备受青睐。本篇内容就以自己服务器来更新的方式实现。
前面简单的说了些基本原理,接下来先上一张具体的更新流程图:


上面流程图中展示了如何实现更新的步骤,可以总结为如下几点:
进入App根据版本检查是否需要更新:
(1)更新:
下载最新JsBundle文件以及所需要的图片资源等,下载完成后解析最新JsBundle文件。
(2)不更新:
判断本地是否还有缓存的JsBundle文件:
1>存在:
本地存在JsBundle,即有过热更新操作。那么App直接加载在缓存目录下的JsBundle文件。
2>不存在:
本地不存在JsBundle,即之前从未有过热更新操作。那么App只能使用初始化时打包在assets目录下的index.android.bundle文件。
Ok,根据上面的流程,我们来看下代码实现过程:

二、具体实现

2.1.检查是否需要更新

http://odp9ddz40.bkt.clouddn.com/hot_1.png

实现步骤即请求服务器中的版本号,然后与本地版本号进行对比,此处我为了代码清晰易懂,直接执行下载更新的流程。
2.2.Android为我们提供了下载工具类:DownLoadManager,我们使用它来执行下载
http://odp9ddz40.bkt.clouddn.com/hot_2.png

首先去判断是否存在有下载的更新压缩包,如果有,则先删除旧的,然后下载最新压缩包。
2.3.下载完成后,DownLoadManager会发出一个DownloadManager.ACTION_DOWNLOAD_COMPLETE的广播,在收到广播后,对比下载任务ID
http://odp9ddz40.bkt.clouddn.com/hot_3.png

因为我们下载的是Zip压缩文件(Zip压缩文件体积下,有效控制了由于更新文件大以及图片资源占用给用户带来消耗流量的问题),所以我们需要先解压
2.4.解压Zip
http://odp9ddz40.bkt.clouddn.com/hot_4.png

2.5.解压完成后,加载最新Bundle和图片资源
如何控制RN加载Bundle的方式呢?没错,0.26版本之后的RN系统在ReactApplication下的ReactNativeHost为我们提供了getJsBundleFile方法,在该方法中默认返回null,即加载assets下的bundle文件。我们可以根据条件来加载不同目录下的bundle文件即可
http://odp9ddz40.bkt.clouddn.com/hot_5.png

在当我们下载好最新更新文件后,跳转到RN界面,即会执行getJSBundleFile方法来执行加载Bundle文件的方式。在实际应用当中,我们可以在Splash页面去执行检查更新下载,然后在跳转到RN界面时,最新文件就会呈现出来。
如何获取最新的bundle文件和图片资源呢?我们在RN项目根目执行以下命令来得到bundle文件和图片资源:
react-native bundle --entry-file index.android.js --bundle-output ./bundle/index.android.bundle--platform android--assets-dest./bundle--dev false
(1)--entry 入口js文件,android系统就是index.android.js,iOS系统就是index.ios.js
(2)--bundle-output 生成的bundle文件路径
(3)--platform 平台
(4)--assets-dest 图片资源的输出目录
(5)--dev 是否为开发版本,打正式版的安装包时我们将其赋值为false
执行命令之前,首先要在根目录下创建好bundle文件夹,bundle文件和图片资源将会输出到已创建好的bundle文件夹下。
解压后的最新更新文件:
http://odp9ddz40.bkt.clouddn.com/hot_6.png

到此,我们便完成了代码的热更新工作。

三、优化补丁包更新

大家可能会说,如果bundle太大的情况下怎么办呢?没错,这个问题同样在博客开始也提到了。打包成zip也是为了减小更新文件体积,减少用户流量消耗,同样,我们也可以生成用生成补丁包的方式来进一步减小更新包zip的体积。
初始项目发布时,生成并保留一份index.android.bundle文件。有版本更新时,生成新的index.android.bundle文件,使用google-diff-match-patch对比两个文件,并生成差异补丁文件。app下载补丁文件,再使用google-diff-match-patch和assets目录下的初始版本合并,生成新的index.android.bundle文件。ok,来看下核心代码:
3.1.生成补丁包


http://odp9ddz40.bkt.clouddn.com/hot_7.png

3.2.下载完成,解压后执行mergePatAndAsset方法将Assets目录下的index.android.bundle和pat文件合并


http://odp9ddz40.bkt.clouddn.com/hot_8.png

3.3.合并
http://odp9ddz40.bkt.clouddn.com/hot_9.png

从上述代码中我们看到,合并分为如下过程:
(1)获取Assets目录下的bundle文件,转换为字符串

(2)解析.pat文件将其转换为字符串
(3)调用patch_fromText获取patches补丁包
(4)调用patch_apply方法将第四步中生成patches补丁包与第一步中获取的bundle合并生成新的bundle
(5)保存bundle
3.4.读取pat文件的方法:


http://odp9ddz40.bkt.clouddn.com/hot_10.png

3.5.读取Assets目录下的bundle文件:
http://odp9ddz40.bkt.clouddn.com/hot_11.png

以上步骤执行完成后,我们就获取到了新的bundle文件,继而加载新的bundle文件,实现React Native热更新。

四、效果演示

为了演示,先来看更新前的界面:

http://odp9ddz40.bkt.clouddn.com/hot_12.gif

点击加载最新Bundle,下载最新的,然后加载最新界面:
http://odp9ddz40.bkt.clouddn.com/hot_13.gif

以上就是使用React Native关于热更新的内容,其实还有很多不足地方,例如对更新文件进行加密,防止被恶意修改等等一些内容还需要不断完善。
整个DEMO实例源代码下载地址:https://github.com/songxiaoliang/ReactNativeApp
刚创建的React Native交流九群:536404410,欢迎各位大牛,React Native技术爱好者加入交流!同时博客右侧欢迎微信扫描关注订阅号,移动技术干货,精彩文章技术推送!
尊重原创,转载请注明:From Sky丶清(http://www.lcode.org) 侵权必究!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容