前言
这里讨论的动态部署方案,就是指通过不发版的方式,将新的内容、新的业务流程部署进已发布的App。因为苹果的审核周期比较长,而且苹果的限制比较多,业界在这里也没有特别多的手段来达到动态部署方案的目的。这篇文章主要的目的就是给大家列举一下目前业界做动态部署的手段,以及其对应的优缺点。然后给出一套我比较倾向于使用的方案。
其实单纯就动态部署方案来讲,没什么太多花头可以说的,就是H5、Lua、JS、OC/Swift这几门基本技术的各种组合排列。写到后面觉得,动态部署方案其实是非常好的用于讲解某些架构模式的背景。一般我们经验总结下来的架构模式包括但不限于:
Layered Architecture
Event-Driven Architecture
Microkernel Architecture
Microservices Architecture
Space-Based Architecture
我在开篇里面提到的MVC等方案跟这篇文章中要提到的架构模式并不是属于同一个维度的。比较容易混淆的就是容易把MVC这些方案跟Layered Architecture
混淆,这个我在开篇这篇文章里面也做过了区分:MVC等方案比较侧重于数据流动方向的控制和数据流的管理。Layered Architecture
更加侧重于各分层之间的功能划分和模块协作。
另外,上述五种架构模式在Software Architecture Patterns这本书里有非常详细的介绍,整本书才45页,个把小时就看完了,非常值得看和思考。本文后半篇涉及的架构模式是以上架构模式的其中两种:Microkernel Architecture
和Microservices Architecture
。
最后,文末还给出了其他一些关于架构模式的我觉得还不错的PPT和论文,里面对架构模式的分类和总结也比较多样,跟Software Architecture Patterns
的总结也有些许不一样的地方,可以博采众长。
Web App
实现方案
其实所谓的web app,就是通过手机上的浏览器进行访问的H5页面。这个H5页面是针对移动场景特别优化的,比如UI交互等。
优点
- 无需走苹果流程,所有苹果流程带来的成本都能避免,包括审核周期、证书成本等。
- 版本更新跟网页一样,随时生效。
- 不需要Native App工程师的参与,而且市面上已经有很多针对这种场景的框架。
缺点
- 由于每一页都需要从服务器下载,因此web app重度依赖网络环境。
- 同样的UI效果使用web app来实现的话,流畅度不如Native,比较影响用户体验。
- 本地持久化的部分很难做好,绕过本地持久化的部分的办法就是提供账户体系,对应账户的持久化数据全部存在服务端。
- 即时响应方案、远程通知实现方案、移动端传感器的使用方案复杂,维护难度大。
- 安全问题,H5页面等于是所有东西都暴露给了用户,如果对安全要求比较高的,很多额外的安全机制都需要在服务端实现。
总结
web app一般是创业初期会重点考虑的方案,因为迭代非常快,而且创业初期的主要目标是需要验证模式的正确性,并不在于提供非常好的用户体验,只需要完成闭环即可。早年facebook曾经尝试过这种方案,最后因为用户体验的问题而宣布放弃。所以这个方案只能作为过渡方案,或者当App不可用时,作为降级方案使用。
Hybrid App
通过市面上各种Hybrid框架,来做H5和Native的混合应用,或者通过JS Bridge来做到H5和Native之间的数据互通。
优点
- 除了要承担苹果流程导致的成本以外,具备所有web app的优势
- 能够访问本地数据、设备传感器等
缺点
- 跟web app一样存在过度依赖网络环境的问题
- 用户体验也很难做到很好
- 安全性问题依旧存在
- 大规模的数据交互很难实现,例如图片在本地处理后,将图片传递给H5
总结
Hybrid方案更加适合跟本地资源交互不是很多,然后主要以内容展示为主的App。在天猫App中,大量地采用了JS Bridge的方式来让H5跟Native做交互,因为天猫App是一个以内容展示为主的App,且营销活动多,周期短,比较适合Hybrid。
React-Native
严格来说,React-Native应当放到Hybrid那一节去讲,单独拎出来的原因是Facebook自从放出React-Native之后,业界讨论得非常激烈。天猫的鬼道也做了非常多的关于React-Native的分享。
React-Native这个框架比较特殊,它展示View的方式依然是Native的View,然后也是可以通过URL的方式来动态生成View。而且,React-Native也提供了一个Bridge通道来做Javascript和Objective-C之间的交流,还是很贴心的。
然而研究了一下发现有一个比较坑的地方在于,解析JS要生成View时所需要的View,是要本地能够提供的。举个例子,比如你要有一个特定的Mapview,并且要响应对应的delegate方法,在React-Native的环境下,你需要先在Native提供这个Mapview,并且自己实现这些delegate方法,在实现完方法之后通过Bridge把数据回传给JS端,然后重新渲染。
在这种情况下我们就能发现,其实React-Native在使用View的时候,这些View是要经过本地定制的,并且将相关方法通过RCT_EXPORT_METHOD
暴露给js,js端才能正常使用。在我看来,这里在一定程度上限制了动态部署时的灵活性,比如我们需要在某个点击事件中展示一个动画或者一个全新的view,由于本地没有实现这个事件或没有这个view,React-Native就显得捉襟见肘。
优点
- 响应速度很快,只比Native慢一点,比webview快很多。
- 能够做到一定程度上的动态部署
缺点
- 组装页面的元素需要Native提供支持,一定程度上限制了动态部署的灵活性。
总结
由于React-Native框架中,因为View的展示和View的事件响应分属于不同的端,展示部分的描述在JS端,响应事件的监听和描述都在Native端,通过Native转发给JS端。所以,从做动态部署的角度上讲,React-Native只能动态部署新View,不能动态部署新View对应的事件。当然,React-Native本身提供了很多基础组件,然而这个问题仍然还是会限制动态部署的灵活性。因为我们在动态部署的时候,大部分情况下是希望View和事件响应一起改变的。
另外一个问题就在于,View的原型需要从Native中取,这个问题相较于上面一个问题倒是显得不那么严重,只是以后某个页面需要添加某个复杂的view的时候,需要从现有的组件中拼装罢了。
所以,React-Native事实上解决的是如何不使用Objc/Swift来写iOS App的View
的问题,对于如何通过不发版来给已发版的App更新功能
这样的问题,帮助有限。