跨平台
关于BeesAndroid项目
BeesAndroid项目提供了一系列的工具、理论分析与方法论,旨在降低Android系统源码的阅读门槛,让读者更好的理解Android系统的设计与实现。第一次阅览本系列文章,请参见导读,更多文章请参见文章目录。
自己接触跨平台容器也有快一年的时间了,站在前人的肩膀上,结合着自己的理解,聊一聊对跨平台容器生态的看法,不当之处多多指正。
背景与历史
跨平台技术解决的核心问题
- 效率:解决在多应用、多平台、多容器上开发效率的问题,一码多端,业务快跑。
- 性能:解决的是业务的性能和体验问题。
跨平台技术的评价指标
- 技术栈
- 研发效率
- 动态化
- 多端一致性
- 性能体验
- 维护成本
- 社区生态
跨平台技术的渲染方案
- WebView渲染:依赖WebView进行渲染,在功能和性能上由妥协,例如PhoneGap、Cordova、小程序(有的小程序底层也采用了ReactNative等渲染方案)等。
- 原生渲染:上层拥抱W3C,通过中间层把前端框架翻译为原生控件,例如ReactNative+React、Weex+Vue的组合,这种方案多了一层转译层,性能上有损耗。随着原生系统的升级,在兼容性上也会有问题。
- 自建渲染:自建渲染框架,底层使用Skia等图形库进行渲染,例如Flutter、Unity。
跨平台技术的发展历史
这里面提一点,React Native和Weex额外增加转译层的做法,目前看来在性能上已经遇到瓶颈,而且系统升级以后,框架维护成本较高,如果未来没有大的重构的话,目前处于走下坡路的状态,其他的方案都处于并存的状态。
| 跨平台框架 | Hybrid App | React Native | Weex | 快应用 | 小程序 | Flutter |
|---|---|---|---|---|---|---|
| 时间 | 2011 | 2015 | 2016 | 2017 | 2017 | 2018 |
| 开发方 | 多个 | Alibaba | 手机厂商 | 多个 | ||
| 支持平台 | Android iOS Web |
Android iOS |
Android iOS Web |
Android | Android iOS |
Android iOS Web |
| 渲染容器 | Android:WebView iOS:WKWebView |
原生容器 | 原生容器 | 原生容器 | 多容器 | 原生容器 |
| 开发语言 | JavaScript | JavaScript(React) | JavaScript(Vue) | JavaScript(原生) | JavaScript(小程序语法) |
Dart |
| 研发效率 | 高 | 一般 | 一般 | 一般 | 高 | 一般 |
| 技术栈 | 前端 | 偏前端 | 偏前端 | 偏前端 | 偏前端 | 偏客户端 |
| 动态化 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| 多端一致性 | 高 | 一般 | 一般 | 无iOS | 高 | 高 |
| 性能体验 | 差 | 一般 | 一般 | 一般 | 一般 | 好 |
| 维护成本 | 低 | 高 | 高 | 高 | 低 | 低 |
| 社区生态 | 活跃 | 不活跃 | 不活跃 | 不活跃 | 活跃 | 活跃 |
注:上面提到渲染性能,只是说在一般概括性的说法,抛开优化谈性能都是不可取的,因此要区分对待。
从发展历程我们来总结一下跨平台容器技术实现的变化
- Hybrid App:JavaScript开发+WebView渲染
- React Native/Weex/快应用:JavaScript开发+原生渲染
- 小程序:JavaScript开发+多容器(多种渲染方式)
- Flutter:Dart开发+原生渲染
容器生态
跨平台容器生态至少可以分为三个方面:
- 前端框架生态
- 容器统一层
- 容器层
前端框架生态
前端框架生态直接面向的是业务,它应该具备两个特点:
- 拥抱W3C生态
- 相对稳定性
它应该是拥抱W3C生态的。W3C生态是一个繁荣且充满活力的生态,它会发展的更久更远。试图抛弃W3C生态,自建子集的做法很难走的长远。这从微信小程序、Flutter都推出for web系列就能看出端倪。
**它应该是相对稳定的。**不能说我们每换一套容器,前端的业务就需要重新写一遍,例如我们之前做H5容器,后来做小程序容器,因为DSL不通,前端要花大力气将业务重写。虽然小程序是一码多端,但是我认为这并没有解决效率问题,主要存在两个问题:
- 前端的学习成本增加,小程序的DSL还算简单,Flutter的Widget体系学习起来就需要花上一点时间,这些对于团队来说都是成本。
- 业务代码重写,大量逻辑需要梳理,而且老业务并不一定都适合迁移到新容器上,比如小程序本来就是个很轻量的解决方案,但是我们在上面堆积了很多功能,造成了严重的体验问题。
在这种情况下,业务很难实现快速奔跑。所以说不管底层容器怎么变,前端的框架一定是相对稳定的。而这种稳定性就有赖于容器统一层。
容器统一层
容器统一层是在前端框架和容器层之间的一个层级。它定义了容器提供的基本能力,这些能力就像协议一样,是相对稳定的。
协议是非常重要的,就像OpenGL协议一样,有了OpenGL协议,不管底层的渲染方案如何实现,上层的调用是不用变的。对于我们的业务也是一样,围绕着容器统一层,我们需要沉淀通用的解决方案。
- 统一API解决方案
- 统一性能解决方案
- 统一组件解决方案
- 统一配套设施解决方案
- 等等
这些东西不能说每搞一套容器,我们都要大刀阔斧重来一遍,这种做法是有问题的。已经做过的东西,遇到新的技术就推倒重来,只能说明以前定义的方案考虑不周全,没有考虑沉淀统一和扩展的情况。
如果我们自顾自的一遍遍做着功能重复的技术方案,业务能等着我们吗。
容器层
容器层的迭代核心是为了在解决效率问题的基础上最大化的解决性能和体验问题。
早期的ReactNative模式解决了效率了问题,但是多了一个通信层(ReactNative是依靠将虚拟DOM的信息传递给原生,然后原生根据这些布局信息构建对应的原生控件树来实现的原生渲染)存在性能问题,而且这种转译的方式需要适配系统版本,带来更多的兼容性问题。
微信后续又推出了小程序方案,在我看来,小程序方案不像是一个技术方案,它更像是一个商业解决方案,解决了平台大流量规范管理和分发的问题,给业务方提供通用的技术解决方案,当然小程序底层的渲染方案也是多种多样的。
后起之秀Flutter解决的痛点是性能能力,它自建了一套GUI系统,底层直接调用Skia图形库进行渲染(与Android的机制一样),进而实现了原生渲染。但是它基于开发效率、性能以及自身生态等因素的考虑最终选择了Dart,这种做法无疑是直接抛弃了繁荣的前端生态,就跨平台容器的发展历史来看,在解决效率与性能的基础上,最大化的拥抱W3C生态,可能是未来最好的方向。Flutter目前也推出了Flutter for Web,从它的思路来看,是先打通Android与iOS,再逐步向Web渗透,我们期待它的表现。
容器技术是动态向前发展的,我们今年搞Flutter,明年可能还会搞其他技术方案。在方案变迁的过程中,我们需要保证业务快速平滑的过度,而不是每次大刀阔斧的再来一遍。
随着手机性能的提升,WebView的性能也越来越好,Flutter又为解决性能问题提供了新的思路,一个基础设施完善,体验至上,一码多端的跨平台容器生态值得期待。