乔帮主发布iPhone以降,把世界推向了智能手机时代,随之而来的是移动互联网大潮,一时间移动应用开发变得炙手可热起来,渐渐的超越了传统桌面端和传统前端,成为了主流。随之而来的就是重复开发的问题,同样的业务需要在Android上面实现一次,在iOS上面实现一次,通常也需要在Mobile Web(移动端H5)实现一次,自此跨端开发成了移动互联时代一个必须要攻克的难题。
大前端开发简史
工程师的使命是让不可能变可能,把可能变简单,可简单变优雅。如果能用同一套代码在不同的端侧都运行,那将是再美好不过的了,毕竟对于端侧业务逻辑一样的,但却要用不同的编程语言,不同的框架,不同的平台,不同的团队各开发一次。如果能够做到「开发一次,多端运行」,将极大的节省人力物力和财力,开发效率也将大大提升。遂业界一直在探索如何跨移动端开发,也即只用一套代码,开发一次,就可以在Android端,iOS端和移动Web端三端运行。
史前时代:Hybrid app
最先出来的框架是Hybrid app(PhoneGap和Cordova),利用Android端和iOS端都对WebView有较好的支持,因此用移动前端(也即网页)的方式来开发应用,绝大多数的业务逻辑都在网页里,Android端和iOS端都是用WebView去展示网页,对于JavaScript在网页中无法实现的,与平台强相关的事情可以通过JavaScript Bridge来调用平台实现的API,称之为JsBridge。
这种架构非常简单,对于Android和iOS来说,使用一个WebView,再实现一些native API就可以了,其余的都是标准的移动前端。得益于平台对HTML 5的支持,以及像jQuery Mobile等优秀的前端库的加持,无论是开发体验还是使用体验,Hybrid app并不差。最重的是它跨平台性特别好,性价比超高,对于UI部分很重,交互 也不复杂的以展示为主的页面来说,这是性价比超高的实现方式。
这个可以称之为史前时代。
黑暗时代:不成熟的各种尝试
Hybrid app方式虽然可行,但在不同的终端上面体验差距很明显。对于性能较好的中高端设备,因为设备整体性能较好,Hybrid app体验尚可,虽然与原生UI相比仍有差距,但属于可接受范围。但对于中低端设备来说,WebView不但性能差,而且兼容性不好,体验严重差于原生UI。另外,如果UI交互变得复杂,或者对体验和实时性操作要求比较高(如文档编辑类等)Hybrid方式与原生更是相距甚远。工程师们开始尝试新的方案。
比如坊间有用json格式来定义UI,定义好格式后,每个端拿到一坨json数据解析,然后生成UI。这其实都算不上是框架,其实就是用json来描述一个页面,解析与构建UI仍是由每个端自己搞,顶多算是一种UI描述格式。但难以通用,并且只能描述UI的静态结构,无法有动态的行为之类的。这种方案也曾有不少大厂用过,它非常适用于局部的,并不复杂的UI,业务逻辑固定,但UI排版样式可能随时会变页面。但要说用它来写整个应用,是不现实的。
这期间Google也做了尝试,搞出一个叫做j2objc的工具,它能把Java代码翻译 成为Objective-C代码,转换后的Objective-C代码无需修改可以直接编译运行。显然,这个工具并不适用于UI,因为UI都是与平台强相关的,需要大量的依赖于平台的SDK,并不是把代码「翻译」过来就完事了。这个工具适用于非UI部分的业务逻辑代码,效果也非常的好,经其转换后的代码可以直接编译运行。据说Google自己也在用,当时的GMS产品Google Inbox等都用j2objc达到了70%代码共用。
这是大前端的一个黑暗时代,虽然大家都在尝试,但始终没有一个比较理想的完整的解决方案。
黎明的署光:划时代的ReactNative
Hybrid方式最大的问题在于WebView是性能和体验的瓶颈,WebView之所以是瓶颈 在于它是一个完全的浏览器,它要完全支持JavaScript,HTML和CSS。但随着HTML5和Web前端技术的发展,有很多库可能只用JavaScript来实现。JavaScript独立出来与Node.js结合(严谨的说是JS引挚),同样可以做前端,但却少了HTML和CSS的拖累,沿着这个思路非死不可(彼时叫做Facebook,现在叫做Meta)推出了一个跨移动端平台的开发框架ReactNative。它是基于Facebook的React框架,做了面向移动端的延伸。它的主要实现方法是用React来写页面,这是一个基于JavaScript语言的声明式UI框架,加入了一个虚拟DOM层,用以屏蔽频繁的DOM改动,然后再把虚拟DOM转成一个渲染树,最后由Node开出口子,把渲染树用Native的API去实现,由此实现了原生UI。
ReactNative可以实现跨三端,页面用React写好后,不用修改就可以在Web,Android和iOS上运行。一经发布引发了巨大反响,坊间众人皆拍大腿「卧草,还可以这样玩儿啊!」。
ReactNative是划时代的,因为它确定了跨端框架的基本结构:声明式UI,虚拟DOM和渲染树,用原生API去实现渲染树(映射为Native的组件,或者用Native graphics API去实现渲染树)。后续的跨端框架基本上都是这个路子。
群星闪耀的当下
时光荏苒,移动互联大潮已经过了十几年,技术也层出不穷,新的框架在不断的涌现。现如今跨端这一领域百花齐放,群星闪耀,各大框架经过几年的沉淀与发展已经比较成熟。除了ReactNative以外,还有了NativeScript,Flutter以及CMP。这其中NativeScript其实与ReactNative差不多,唯一的区别在于它允许用JavaScript家族语言(如TypeScript和CoffeeScript),以及不限制开发框架,可以用Vue.js或者Angular.js来写UI。
当然,最为广泛流行,业界使用最多的当属于Flutter和ReactNative,CMP作为一颗新星也越来越受关注。
流行框架对比
这里简要对比一下最为流行的ReactNative和Flutter以及新星CMP,以方便使用者做出更好的选择。
框架 | 开发者 | 开发语言 | UI开发库 | 支持的端 |
---|---|---|---|---|
ReactNative | Meta | JavaScript | React | Android, iOS, Web |
Flutter | Dart | Android, iOS, Desktop, Web | ||
CMP | JetBrains | Kotlin | Jetpack Compose | Android, iOS, Desktop, Web |
ReactNative和Flutter都相对较成熟和稳定了,使用者也较多,社区很活跃。ReactNative更适合移动端,而Flutter能跨的端和CMP要更多一些。此外,Flutter和CMP与其他框架最大的区别在于它使用Skia库构建了一个渲染引挚,可以直接把渲染树渲染成为平台支持的更为底层的canvas,直接接入native层的graphics API而不是映射成native组件,为此,它的渲染效率更为高效一些,进而性能更优一些,可以把它们想像成为一个浏览器。
技术栈也不一样,ReactNative是基于Node和JavaScript,属于前端技术栈,与前端融合更为紧密一些;而CMP是基于Kotlin和JVM与Android更为紧密一些,属于Java派系;而Flutter自成一派。
选择是痛苦的
实事求是的来说Flutter是当前最为成熟 也最为完备的一个跨端框架,只不过可能学习成本略大,对于大部分同学来说Dart是一门小众的编程语言。而ReactNative最大的问题就在于React,它太前端化了,对于客户端同学来说写一坨HTML式的标签还是相当难受的。
应该说Flutter已经非常成功了,达到了它应该有高度,实现了它的价值,换句话说它的前景也不是特别明朗了,因为它已经很成熟了,所以有传言谷歌内部也在裁撤Flutter的研发资源。ReactNative也一样,这么多年了,版本还没有到1.0。
而CMP刚刚兴起,使用起来非常的方便和简单,它的安装与配置是所有框架之中最为简便的(只需要安装一个Android Studio的插件,其余的都是编译插件和依赖,并不像Flutter和ReactNative都需要在开发机器上安装其他东西),前途无量,非常值得投入。并且Flutter对于谷歌来说九牛一毛,是非常不起眼的东西,谷歌毕竟家大业大,像谷歌和Meta等巨头现在都在狂卷AI,其他的小业务都不受重视。但CMP不一样,JetBrains本身就是专门搞开发工具的,这是他们的主业肯定 会好好搞,把CMP与其IDE深度结合,对于开发者使用起来那就相当的方便了。事实上JetBrains已经开始弄了,它的最新的IDE Fleet(一个通用的IDE)将会深度绑定CMP,非常值得期待。
综合考虑,给出的建议就是如果是一个纯新的项目,特别是MVP阶段,不要犹豫就是用Flutter 。而如果是现有项目,想要跨端,就选择CMP,它是对现有项目最为友好的一个。除非你是资源前端且是React粉,否则不要考虑ReactNative。
框架只能解决一部分问题
最后想说的是,对于跨端开发,框架只能解决一小部分问题。
跨端开发最难的地方在于合理的架构和团队的协同。架构需要做好层与层的隔离,特别是把与平台强相关的API做好隔离层,以最大限度 的共用代码,如果到处都是粗粒度的平台相关的实现,复杂度将急剧上升,那最后会变成多端的拼盘而非一个跨端项目。人员的协作应该以功能为单位来划分而不能再以端的维度,要彻底消灭端的思维,要以UI,功能和业务逻辑角度来思考问题,这样才能更好的协作。总之跨端对团队的要求更高,否则只会制造更多的问题。
人的问题永远要比技术问题要复杂一些,举个最简单的例子,以往每个端各自为政,Android端某个同学犯了错,顶多就是Android端不能用了,可能最多就3.25。真跨端了以后,再犯错那可就是所有端都搞挂了,可能最少是3.25起步,这里头的差别还是相当大的,如果没有强有力的大一点的老板来推,是很难推得动的。
研发同学都喜欢折腾,光完成业务是很无聊的,也不可能出成绩,都想方设法的搞出点「技术产出」(俗称造轮子)。记得ReactNative刚出来时,坊间很热情都在把其引入到各自的业务中去,但最终的结果是,没有人会真的在业务中重点使用,而是都花心思搞出了一套属于自己的跨端框架,并且向其他团队推广。年终汇报时,PPT很漂亮:「老板您看,我们不光完成了业务,还搞了一套跨端框架,它比ReactNative好在哪里,已经在我们的业务使用了,也给其他团队推广了」。相反,假如你真的使用了跨端,你咋 汇报?「老板,您看,我们用了别人的跨端技术,成功的实现了跨端,原来三个端15个人能做完的事情,现在只需要8个人!」。老板听了,很激动,3.25终于找到人选了,开猿节流也着落了!
Anyway,总的来说跨端开发更适合业务不复杂,UI交互也不重的中小型App,或者那种UI占比较小非UI逻辑占比大的应用(最典型的就是浏览器),才能发挥出最大的价值。一个比较简单的判断标准就是,如果每个端的研发人员都超过10个人,可能就不太适合用跨平台的开发方式。
References
欢迎搜索并关注 公众号「稀有猿诉」 获取更多的优质文章!
保护原创,请勿转载!