跨端能力一直是近些年来的大热门,我们对跨端能力也一直抱有非常高的期望,我从2016年开始就一直关注着跨端能力的发展,经历了其中各个发展阶段,而目前我们团队也将建设整个跨端平台化能力,这里就来讨论下跨端的一些东西,以及我们的平台化会如何建设整个生态。
我们真的需要跨端能力吗
跨端的发展基本经历了这么几个阶段,h5
->RN/weex
->小程序
->flutter
,而最近flutter成了最火爆的弄潮儿,但是我们可以看到,每种跨端方案在提出之初,都被吹捧为将会颠覆整个客户端开发,而现实却是原生开发依然占据着无法撼动的地位。
我在早期也非常的看好跨端方案,因为这是唯一一种能够同时大量降低业务开发工作量的方案,而且跨端的很多技术方案也是领先原生开发一个世代的,无论从学习成本,开发效率以及一些前后端融合的趋势都有着非常优秀的设计,以至于我一直认为跨端将是原生开发的未来,原生开发模式的终结者。然而后续的现实却深深的打了我的脸,从facebook放弃h5以及RN,阿里放弃weex,说明当时的跨端方案几乎是失败的。为什么我会认为当时的方案几乎是失败的,我们又将如何对待跨端这项技术呢,接下来我们可以简单的分析一下。
早期的跨端方案是失败的
早期的跨端方案基本都是打着消灭原生开发的口号而进行的,从Facebook对h5的各种优化来看,认为当前的网页早已经能够承担所有能力了,而且随着手机摩尔定律的发展,不用几年,手机就会和电脑一样,能够很好的承载网页了。而现实却是Facebook最终还是没有等来那个美好的未来。
随着前端技术的快速发展,衍生出了react和vue这样的技术,这项技术给前端的开发模式带来了巨大的变革,从此前端不需要再依赖jQuery这样去操作具体节点了,所有DOM节点都被抽象化,这给也给一批跨端先驱者们带来了曙光。既然DOM节点可以被抽象化,同样的原生View也可以被抽象化,并通过映射关系,组建原生视图。可以说,这种思路是一个跨时代的想法,第一次前端与原生应用进行了一次激烈的碰撞。这种碰撞也催生了众多的新的思路与设计理念(比如swiftUI,个人也将部分理念贯彻到了原生开发之中,来解决原生开发的一些问题),在跨端方面也催生了RN和weex这两种方案,这两种方案都以write once, run anywhere
这样的主旨努力,想要统一前端、iOS、安卓这几个平台。
但这些技术的最终结果却是很悲惨,Facebook放弃了h5和RN,目前RN也只是开源爱好者在用爱发电了,而阿里也逐步淘汰了weex,可能国内某些厂在内部还在维护一些魔改版。两大创时代的技术创造者最后却放弃了,这让我陷入深深的怀疑,跨端的方向是否是正确的。
大家可能会说,现在还是有大量的公司在使用这种方案,并不代表这项技术是失败的。但我个人认为它的失败在于它并没有完成最早所承诺的能力与效果。
实行这种方案对人员素质要求非常高,需要开发仅对前端、移动端都有所涉猎,在出现一些兼容问题的时候能够自主解决该问题。而现实是这种人才真的太少了,特别是在国内的这种环境,要找到并留住这种人才是非常困难的,而如果人员素质没有达到如此高的程度,那么会大大增加多端的沟通成本,甚至比原生开发需要更多的人力成本(以个人经验来看,一旦涉及到跨端能力接入,那么至少需要1iOS+1安卓+1前端人力,包括接口设计、调试等沟通时间,未必会比原生开发减少太多的人力)。
如果缺乏一个能够掌控全局的人,那么每次需要一个原生能力的时候,便会新增一个接口,而这些接口能力并没有经过良好设计,从而导致这些能力的复用性极差,以至于后期这类接口能力的爆炸,无法维护。这类问题虽然看似比较少见,但在一个业务快速膨胀的团队,仅需要1年时间就可以让沟通成本急剧增加。(不要说文档,如果文档能够解决这类问题,也就不存在前后端接口爆炸的问题了,而且文档也是一种大大增加沟通成本的东西,并且我不相信目前国内有哪个团队在文档这块做到及格的。)
双端有着这种不一致的体验与设计语言,write once, run anywhere
这个理念本身就是一个无法达到的乌托邦,并且react-native自身也认识到这个问题,并没有把run anywhere
作为自己的目标,而是区分对待两端的特殊性,而在上层进行整合这种特殊性,所以依然无法逃避在不同平台实现不同逻辑。而weex则更激进一些,甚至将原生View给映射为div这种前端标签,想要一次性整合3端,然而这种巨大的不一致性所导致的结果是彻底的失败,最终还是仅仅在移动端进行了部分整合。
当然这些跨端方案还有另一个问题就是通信成本特别高,特别是一些实时性、流畅性要求高的场景,往往是达不到要求的。
综上所述,早期的跨端方案在多个维度都没有兑现自己的想法,所以我认为是失败的,但是这些方案却给我们带了一个意料之外的惊喜,那就是动态化,这个之后再说。
特定领域跨端化实践
在经历了早期跨端实践的失败后,大家都开始思考跨端的未来,如果还是想要统一各端的开发,那么很有可能将会经历一样的失败。此时微信找到了一个极好的应用场景,那便是小程序。
小程序这种场景有着这么几个特点:
- 对动态性要求特别高,因为苹果不允许执行下发动态库,所以必须采用动态化特性
- 对性能要求一般,但对功能要求较高,需要能够满足大量现有能力
- 要求较好的隔离性,由于子应用是可以由3方提供服务,那么主应用与子应用之间必须是单向管理的关系,需要严格限制子应用的能力特性,以防被3方软件滥用
- 要求较高的鲁棒性,主应用就相当于操作系统,能够保持每次升级与优化的兼容性与一致性
那么从以上几个特点来看,设计一套简化版的DSL是必须的,同时需要设计自己的通用能力与权限系统,以及OAuth2认证等。而目前最为符合,同时也是最小开发量的就是h5技术,所以目前常见的小程序基本还是以h5容器为主。
小程序的出现,不仅仅是跨端领域的一次新的尝试,同时也是业务领域的一个创举。小程序的出现,将一个普通的应用,演化成一个完整的平台系统,不仅仅给其他公司提供了一个发展的平台,同时也帮助自己巩固自身的平台地位。将一个巨应用,逐步转化为微应用集合,减少各类成本的同时,也极大的丰富了这种功能服务。可以说小程序就是大平台应用的一次战略性布局,当然现在已经展示出了它的价值。
这次,小程序给跨端指明了一个方向,那就是在特定领域创造价值。
统一移动端思潮的亡者归来
flutter的出现,大家又掀起一次跨端思潮的崛起,但这次的崛起,似乎减少了对双端的统一要求(安卓的material与iOS的cupertino),大家似乎已经从狂热的思潮中冷静下来,认识到了各端不一致性的必然性,以及用户对各自平台的接受程度,这次的革新,似乎已经不是write once, run anywhere
这样的呐喊,而更多的是对所有“大前端”的开发模式的一次统一。(有很多人认为write once, run anywhere
就是flutter的目的,并且是跨端的终极模式,个人认为并不是,这个口号官方从来没有喊过,而且flutter的野心比单纯的实现跨端方案要大的多)
flutter的目的并不是单纯的实现一个跨端方案,所以就决定了所采用的技术就不会依赖于各个平台的UI层,它从最基础的GPU绘制开始,完全使用自己的能力,这是一套非常完整的UI框架。由于flutter完全抛弃了各平台的UI层,那么便不存在各个平台的差异性了(这其实也是个坑),理论上可以做到不需要做任何兼容性实现。但现实却是,平台的差异性目前已经深入人心,粗暴的提供一种效果和习惯并不能收获用户最好回应。但是如果你是想要拿着flutter去实现安卓的效果,或者实现iOS的效果,那么你可以打消这个念头了,他能做到的最多是“模拟”,而非“实现”。
那么flutter的应用场景就比较固定了,我们依然只能在一些重业务与展示的场景去使用,而在个性非常突出的场景,以及涉及到大量原生能力的地方,就显得不那么适合了。
为什么我会认为flutter想要打造一个完善的统一的UI开发平台才是其真正的目的。由于目前移动端的开发人员依然比较割裂,而未来的趋势必然是整个前端的大融合,甚至是与部分后端的融合,让业务方去关注整个业务而不是业务的一个点,这样的融合就必须首先统一各端的开发模式以增加效率和人员的流通性,可以说flutter的出现对于移动端未来发展也有深刻的影响。
所以在此看来flutter依旧不能完全实现跨端统一这一乌托邦,但是其引入的很多前端思路将会给目前的客户端开发模式带来足够的冲击。由于flutter这个项目还在快速发展中,所以我会进行持续关注。
跨端能力总结
在进入跨端平台化建设之前,我们花了大量的篇幅来回顾各个时间段的跨端发展历程,我这里更多的采用了批判性的角度去看待这些技术,目的是为了找到各个技术的局限性与应用场景。各种技术都有自己的优势与局限性,我们无法将其单纯的判定为成功与失败。
跨端的思路也给我们带来了一些业务上的创新力与未来开发模式的一次变革机会。我们可以看看如何做所有跨端能力平台化整合。
平台化
目前业务的发展导致当前项目中引入了多种跨端方案,而在如此多的方案中,我们又该如何选择,如何去有效的利用各个能力,这是我们希望完成跨端平台化的初衷。
跨端方案想要解决的问题无非是两大类:
- 动态性(快速迭代)
- 开发效率(成本)
由于客户端应用更新的特性,导致我们的新功能、新特性永远无法第一时间到达用户手上,从安卓碎片化程度来看,就知道想让用户保持更新的习惯是多么困难的了。那么在一些场景,比如活动、微应用等,会非常依赖于实时性调整,就会有强烈的动态能力要求。
而效率问题一直是我们所探讨的,虽然有很多种解决效率问题的方案,但跨端给我们提供的一种思路似乎就是一种万能且直接有效的方案,能够大量缩减客户端的人力,毕竟前端人员比客户端人员会好招的多。
但是跨端方案毕竟不是万能的,在诸多方案上还是拥有大量限制,而理想化的一些优势也需要在特定场景才会有明显的发挥。我们想要组建的平台化,也将会从各个方面去帮助业务与开发人员去正确的选择方案,并且提供一系列完整的能力去保障业务的完好运行。
平台化整体能力
大部分时候,我们关心的都是开发阶段的一些问题与解决,开发虽然是跨端方案影响和作用最大的一个环节,但在整个过程中,开发仅占用一部分环节。既然我们希望做一个平台化的能力,那么我们就必须考虑到整个过程的能力。
首先我们需要明确的是,我们的目标是希望所有参与人员,都去关注整个业务,而不是自己这一环节,之前也说过这是未来业务开发模式的一种革新方向。我们不希望产品提了需求就不管了,也不希望开发测试仅仅跟踪到上线这个环节。目前难以做到这一点的主要原因是因为整个流程是割裂的,不同环节都隶属于不同的团队,业务分工足够细,且需要大量人员参与。这种问题在越大的团队会越明显,那么需要平台化去整合的需求也会越强烈。
同时,在整个过程中,人员的因素太过于复杂,需要协调好各个人员与角色,显然不可以仅仅通过沟通与默契来解决,我们必须在整个过程中加入足够多的自动化过程,来推动整个流程的前进,而这自动化的过程,就需要平台化的能力。
跨端方案有很多选择,其之间有很多的相同点,也有很多的区别,而我们在整个过程中,如果因为这其中的不同,从而分化出不同的开发流程,反而会给所有人带来很大的困惑,增加各自的人力成本。
所以可以看到,平台化来整合所有能力也是非常重要的。
业务维度细化
如果需要实现以上所说的全流程整合,那么每个业务功能则必会细化为一个个微服务,或者说是微应用。每个业务模块也是按照一个应用的流程来管理。
由于这些应用(业务)所承载的服务其实是比较小的内容,所以人员可以变得灵活调配,与普通开发人员调动不同,调配的不仅仅是“人力”,而是微型“团队”,以此也可以大幅减少沟通成本。
业务细化肯定会带来大量的微应用,就像淘宝这样的巨应用,存在着无数的微应用。我们需要管理所有的微应用,则不论使用跨端技术,都需要提供一套统一的管理流程。
在我们拥有这一个完整的流程后,可以来看看每个阶段需要哪些东西。
技术选型
在业务方案的选择中,我们可以提供一个简单的筛选条件,但是并不是一个强制的约束。
在具体的业务场景中,我们所需要考虑会比这些条件多的多。比如有些强依赖原生能力的业务需求,如果我们使用跨端方案去实施,最终结果可能完全的违背了跨端的优势,从而导致多端开发的成本直线上升,可能短时间内看似美好,但从长远来看,将会陷入维护的泥潭。
所以这在很多场合是一个比较经验主义的过程,在我们选型的时候,不要先入为主的去决定使用哪种技术,而应该仔细分析业务场景,使用什么技术可以满足需求的同时,尽可能的减少成本。
框架
在引入跨端方案的时候,如果我们毫无节制与约束的使用,最终肯定会变得非常糟糕,那么在此基础上必须有一定的规范来组织与约束大家的使用。
那么下面我们从组织结构、抽象层、沙盒化三个角度进行分析。
组织结构
我们的结构大致分为以上几个层次,这里解释一下中间2层代表的是什么。
- 基础能力桥接层,是与业务无关的能力,是组建所有应用都需要使用到的能力,可以认为这是一套像POSIX标准接口的定义。所有app内的这一层都是相同的,那么在我们想要移植一个跨端应用到另一个app的时候,就会变的非常简单。事实上我们也的确有一些这样的需求。另一个好处是,统一的标准能够让开发人员更好的进行跨应用间的开发,就像为什么支付宝会故意去抄袭微信小程序的api规范一样。
- 业务相关桥接层,每个应用必然是会有各自业务的特殊性,导致一些无法进行标准化与通用的能力,那么我们就需要这一层来做一些脏活了。
抽象层
为了满足上述组织结构中的标准接口定义,那么我们必须要引入一个抽象层,来屏蔽各个跨端技术与app之间的不同。
我们的抽象层大致是这么设计的,实现方案这里就不讨论了,后续会增加一篇该方案的文章[Native RPC]。抽象层给使用者与开发者都屏蔽了多端的特性,所表现出来的是完全的一致性。
我们会有一个专门管理接口定义的平台,从该平台上可以自动生成接口调用代码与demo工程,这样可以大大减少接入、测试、回归等成本。
沙盒化
业务细化后我们必须面对的是这些业务对主应用的影响,以及相互之间的影响。这种影响客户端以及平台层面上是无法把控的,所以需要对各个微应用之间进行沙盒化隔离。
沙盒化后带来的另一个需求则是权限管理,由于目前业务都是面向内部的,所以权限方面要求不是特别严格,这里暂不将权限控制作为重要的一环。
业务层多平台统一
上面所涉及的都是跨端与原生之间的一个统一,那么在各个跨端之间的也可以进行一次统一,比如比较有名的有Taro, rax等。
但这种统一仅仅是为了降低前端开发的学习成本与一些降级策略,强行将这些东西糅合到一起,反而可能会导致开发成本变高,不兼容性与性能下降。在我们有比较固定的人力做单平台业务开发的时候,完全没有必要再引入一层复杂的适配,带来额外的复杂度。
这种方案的适用场景比较局限,适合大量且业务复杂度不高的业务,可以快速搭建与上线,适合多平台3方应用的接入,比如各个平台的小程序。
所以这里并不考虑把这种方案作为我们其中一个目标,就像阿里也并没有吧rax作为内部的主流技术。
测试
由于我们的跨端能力大部分是使用在业务场景中,所以大部分场景做自动化测试的成本都非常高,所以测试环节基本将会是黑盒测试。而得益于部分跨端技术的动态性,问题的修复成本与原生开发相比会小很多。
线上监控
我们选择跨端应用的时候,会比较担心一些跨端应用的负面效果,比如性能,错误率等,所以必须建立比较完善的线上监控系统。
监控系统应该具备我们普遍会关心的一些数据,比如加载时长、错误率、性能指标等,同时提供横向对比的能力,提供业务方一个指导性的意见,同时增强线上预警的能力。
现在这么多不同的跨端技术方案,面临的问题是监控系统的分散,从而无法形成有效的闭环,所以建立一个统一的完整的系统,串联整个迭代链路。
总结
随着跨端技术的发展与应用,也给我们的很多基础设施提供了巨大的挑战,如何将跨端的优势真正的发挥出来,来提高我们的效率与灵活性,这是我们必须面对与解决的问题,而在这之中,如何完善与整合多端能力则是重中之重。