背景介绍
APP的热更新技术是一种防御编程,应用场景是:线上发现了bug,如果要发新版本修复,那么由于苹果的审核周期较长,来不急了,所以需要一种不走苹果审核流程也能解决Bug的技术手段。
bang590/JSPatch 目前已经是事实标准,有很多APP在用Who is using JSPatch?
功能简介
“JSPatch 可以让你用 JavaScript 书写原生 iOS APP。只需在项目引入极小的引擎,就可以使用 JavaScript 调用任何 Objective-C 的原生接口,获得脚本语言的优势:为项目动态添加模块,或替换项目原生代码动态修复 bug。”
这段话说得非常清楚,是用JavaScript调用Object-C,那么对于Swift写的工程呢?只能说是部分支持,在基础用法-Swift已经有很好的说明。结合这篇文章,应该会有比较清楚的区分Swift Runtime分析:还像OC Runtime一样吗?
可以使用 JSPatch Convertor 自动把 Objective-C 代码转为 JavaScript 代码。JS代码不需要和iOS客户端代码一起发布,所以这个工具离线使用,不需要整合进工程。在需要hotfix的JS文件时再用,降低写JS代码的难度。在写测试用例,或者实际使用的时候会有用,但是自动生成的代码还是要人工检查过再用比较好。
语言选择Object-C,不选Swift;用Swift的话,JSPatch有时候不起作用,就没有引入的必要了。
客户端使用
- 初始化
[JPEngine startEngine]
- 执行脚本
[JPEngine evaluateScript:script]
需要考虑的是JS脚本如何加密,如果保证安全,如何取得,执行时机等等。这些方面,需要好好设计一下。
JS执行方式
- exec js directly === 直接执行JS脚本
- exec js file from network === 给个url,直接从网络下载JS脚本执行
- exec local js file === 执行本地JS文件
以上三种是官网中的例子,实际中都比较难直接用
直接执行JS脚本?=== 本地知道要怎么改了,为什么不直接改掉,还绕这么一大圈?
给个url,直接从网络下载JS脚本执行?=== 明文传输,被人改了怎么办?
执行本地JS文件 === 还是那句话,本地知道要怎么改了,为什么不直接改掉,还绕这么一大圈?
那么实际怎么用呢?
JS文件保存到服务器,JS文件内容加密
JS文件通过下载通道,下载到客户端
客户端执行本地JS文件,完成bug修复
安全策略
JS文件传输,需要保证文件不被替换,一般用MD5
JS文件内容进行加密,比如AES128
版本管理
后台需要知道哪个APP要打补丁?一般可以用bundleId来区分
哪个版本需要打补丁?一般通过version和build两个字段可以确定
后台存储就按照hotfix -> osType -> bundleId -> version ->build的目录结构进行存放
补丁文件固定为patch.js,md5值事先算好,放在md5.txt中,当然文件类型可以按照实际情况自定义
后台根据客户端提交的osType,bundleId,version,build等进行查找,能找到补丁文件,就说明需要热更新,否则就不需要
JS文件是否要缓存?
- 观点1:不需要缓存,热更新一般用于紧急bug,流程控制如果不是太烂,没有多少内容的,所以每次启动,去下个补丁,执行一下,用完就扔,省得麻烦。至于没网络的情况下,APP一般都不正常,热补丁本身就没有多少意义。
- 观点2:需要缓存,同一份补丁只要下载一次就好,没有必要重复下载。并且,下载还有延迟,也不能保证文件一定很小。没网络的情况下,有缓存也能起到热更新的作用。
- 观点3:补丁的执行不能依赖网络。执行的是缓存中的补丁文件。有网络,需要更新补丁文件,才下载更新,替换补丁文件。这个方案的问题就是第一次肯定没补丁,要先下载,下次启动再执行补丁文件。另外,网络,下载可能需要耗费比较长的时间,补丁执行太靠后,Bug可能还是会重现。所以,执行补丁和下载更新补丁应该是两个完全不同的过程。最终,这种观点被团队采纳。
先执行,再下载;下载的文件等下次启动再用。
更新时机
一般情况,放在didFinishLaunchingWithOptions:中,程序启动时,一次执行就好了。
放在applicationDidBecomeActive:中,是为了照顾那些不关程序,直接按Home键的人。不过这个函数可能会多次执行,所以要引入一个定时器,(间隔1小时),防止反复执行。
第三方平台
基于JSPatch开源代码,出现了iOS App 热更新服务平台
思考过就知道,JSPatch API的使用已经非常简单,但是补丁js文件的存储,加解密,传输,版本管理才是麻烦事。这个平台的SDK就是做这些的
就像友盟统计,极光推送,热更新SDK也是差不多的,很小的一个功能入手,做一个服务平台。也像Java中的各种服务架构
至于Swift,静态语言,以后怎么发展,不清楚,至少现在占比还太小
JavaScript目前的趋势越来越强,不得不关注。动态特性是最重要的特点。