前言

每当我们评估新技术时要问的第一个问题就是“它会给我们的业务和客户带来哪些价值?”,工程师们很容易对闪闪发光的新事物着迷,却经常会忽略这些新事物其实可能对我们的客户没有任何好处,反而只会让现有的工作流程更加复杂。

2021年3月3号,google宣布Flutter 2Flutter的重大升级,使开发人员能够为任何平台创建美观,快速且可移植的应用程序。针对web,移动和台式机构建的下一代Flutter。用户可以使用相同的代码库将本机应用程序发布到五个操作系统:iOS,Android,Windows,macOS和Linux; Windows Vista,Windows XP和Windows XP。以及针对Chrome,Firefox,Safari或Edge等浏览器的网络体验。Flutter甚至可以嵌入到汽车,电视和智能家电中,为环境计算世界提供最普遍和最便携式的体验。

提到Flutter,就不得不说一下它的前世今生,Flutter是Google为Fuchsia操作系统设计的应用开发方式。Fuchsia OS要兼容廉价物联网设备,要求对硬件的消耗降低,并且为了避免与oracle的java打官司,Fuchsia 使用了dart语言+flutter界面库的方式。从设计上来看,这套方案的性能确实够高。dart虽然属于大前端范畴,但dart是和java一样的强类型语言,这让dart虚拟机可以做很多优化,性能方面超出了js。dart曾经与typescript竞争,谁才是更好的js?但不幸输给了typescript,chrome也放弃了内置dart虚拟机的计划。不过dart团队没有解散,几年后,他们借助flutter,再次出现在公众面前。

性能分析和写法的对比

flutter作为界面库(注意它只是界面库,dart语言是另一个项目),它唯一要干的事情就是渲染界面。不像HTML5,flutter界面库连视频、定位等都没有,就是一个纯排版引擎,绘制文字、按钮、图片等常用界面控件。这个排版引擎的特点是简单、高性能。

在3大主流渲染引擎里,webview、react native/weex、flutter,复杂度依次降低,渲染性能依次上升。(uni-app是双渲染引擎,webview和weex都内置了,随便开发者使用切换)

所以我们要清楚,提升性能是有代价的,你究竟想要灵活丰富的css3,还是想要固定flex模式排版,抑或是最简单但高性能的flutter排版?开发便利性和运行性能不可兼得。同时我们要明白,性能的差别,并不是因为Google的chrome团队、Android团队的技术比同公司的flutter团队差。而是flutter提供的布局写法是被限制过的,解析快,所以渲染快。别忘了webview的排版引擎也是世界级工程师用c写的。但通过这种方式提升性能的代价,就是布局复杂的界面时,flutter的代码嵌套的让人崩溃。

我们先举个例子,同样的界面,用HTML和flutter如何实现:

<!-- html实现 -->
<div class="greybox">  <div class=redbox>  smaple text  </div>
</div>  .greybox {  display: flex;  align-items: center;  justify-content: center;  background-color: #e0e0e0; /* grey 300 */  width: 320px;  height: 240px;  font: 18px
}
.redbox {  background-color: #ef5350; /* red 400 */  padding: 16px;  color: #ffffff
}
//flutter实现
var container = new Container( // grey box  child: new Center(  child: new Container( // red box  child: new Text(  "smaple text",  style: new TextStyle(  color: Colors.white,  fontSize: 18.0,  ),  ),  decoration: new BoxDecoration(  color: Colors.red[400],  ),  padding: new EdgeInsets.all(16.0),  ),  ),  width: 320.0,  height: 240.0,  color: Colors.grey[300],
);

可以看出,从代码的写法来说,flutter没有tag和样式的说法,更没有选择器,从头到尾只有dart语言,它的界面控件是用dart代码new出来的,每个控件的样式,是在new的时候设置的类json写法的参数。如果我们要嵌套布局,就要不停的在dart里写child,同时在dart里给child们设样式参数。上面的代码,只是嵌套了1层,实际开发中,dom要嵌套好多层,想象那样的代码。。。所以大家都诟病dart是“嵌套地狱”。或者,你可以这么理解,这是一个只有js,没有html和css的浏览器。你需要用js createElement来创建元素,用js的style方法给每个element设style,反正就是不能写html和css代码。前端都已经发展到各种mvc等视图逻辑分离的架构了,也有了vue组件这种组件化模式方便用各种轮子快速完成界面。你是否能适应dart这种低效的界面开发模式?从开发模式来讲,这确实是一种倒退。浏览器的html提供了tag和样式分离的写法,还有各种各样的选择器,但其实这也是有代价的。它导致webview初始化时要同时先启动webkit排版引擎来解析这些编写随性的html、css,同时还要启动一个js引擎比如v8或jscore来解析里面的js。

而dart就很简单,只启动一个dart引擎,解析严格的dart语法,它不会去操心有些标签未闭合要如何容错,不会判断宽度320后面是px还是rem或者是动态计算百分比。对比这2个引擎初始化时要干的事,差别简直太大了。所以从解析效率上,flutter肯定比webview要高。但从编码灵活性上,flutter写的代码,嗯,难看而低效!

flutter使用的也是flex布局思想,这是一个强嵌套布局模型,比web常规排版引擎的嵌套更多。当界面复杂时,flutter的代码要嵌套几十层,每层的元素的json样式都和元素一起混写在dart代码里,让人崩溃。

有人提出是否可以通过一种预编译的dsl来简化写法,让flutter的开发不这么痛苦。但这个难度太大了,从严格转换为松散是简单的,从松散转换为严格几乎是不可能的。什么意思呢?比如flutter代码转换web代码,是很简单的,flutter已经自带了这个功能。但是想反过来,那可难了。类似的还有,把typescript转为js是容易的,反之,不是绝对不可行,但会复杂到你宁愿去重写一套typescript代码。flutter的性能高,除了简单严格,还有一个特点,就是逻辑层与视图层统一,运行在同一套dart虚拟机下。我们知道rn和weex,也是原生渲染的,它们的性能高于webview。但同为原生渲染的,怎么会慢于flutter呢?其实不是原生渲染慢,而是js和原生通信慢。比如:rn和weex都采用了独立的js引擎(iOS是jscore,Android是v8,最新版rn开始在Android上搞自己的js引擎Hermes),从js与dart的比较上,性能稍逊一筹。但这不是主要问题,因为v8的jit不是盖的,也是编译为原生代码解析的。性能上的主要问题是:rn、weex的js引擎和原生渲染层是两个运行环境。当js引擎联网获取到数据后,通知原生视图层更新界面时,有一个跨环境的通信折损。同样,当用户在屏幕上操作原生视图层时,要给js引擎发送通知,也会产生这个通信折损。

不过这种性能差别,在大多数场景中,用户是感受不到的。比较影响的场景,是跟手式的js响应操作绘制帧动画,或者说js连续操作界面元素方面,flutter折损更少。这个通信折损,其实普遍存在于所有逻辑和视图分离的框架中,包括各家小程序也有这个问题。为了解决react native上js绘制动画卡的问题,曾经的react native拥趸aribnb搞了一个lottie的动画库,但lottie只能静态执行,无法跟手交互。weex更进一步,搞了个BindingX,这个技术很赞,它可以预定义规则,让用户界面在原生层交互时通过预定义规则直接响应,而无需传递给js层。在需要短时间内来回通信的场景时,可以使用BindingX这类解决方案。它的性能和灵活性比rn更强了一些。

在uni-app里,nvue页面可以直接使用bindingx。至于uni-app的vue页面不是基于weex渲染的,它遇到通信折损时,解决方案叫wxs,wxs是一种运行在视图层的js,它的性能和和灵活性都非常高,完全可以达到flutter的水准。说回来flutter,它只有一个dart引擎,没有来回通信产生的性能问题。不过任何事情都是有利有弊的,flutter在普通的界面绘制上效率虽然高,但一旦涉及原生的界面,反而会遇到更多问题。前面已经说过,flutter只是一个基础排版引擎,缺少很多能力,当我们需要在flutter界面上内嵌一个原生的视频播放扩展控件时(flutter没有内置视频播放能力),或者原生的高德地图sdk,那么在拖动视频进度时、拖动地图时,flutter一样会产生原生和dart之间的通信,造成性能损耗。事实上,由于flutter是在一个类canvas环境绘制的,想把一个原生控件嵌入flutter的布局里某些元素之间去排版,还不是一件容易做到的事情,坑很多。每个人都想要一个像css3那样灵活写法的布局引擎,他们给react native和weex提需求,给flutter提需求。殊不知,让这些产品团队实现了css3时,他们的性能优势已经不再了,他们相当于又实现了一遍webview。这种无意义的需求,他们是不会受理了。性能好,有个度,客观地讲,rn/weex调用原生渲染的性能,和flutter的渲染性能,在用户体验上并没有明显区别,甚至在很多场景下,和webview渲染的小程序也没有明显区别。也简单说说webview渲染小程序,为什么性能高,核心是预载。点击一个新页面时,webview是提前创建好的,不会走复杂的webkit、v8的初始化流程,连开发者的js代码,也是预载好的。所以点击新页面时,它的渲染速度和原生应用没什么差别。当然也有个坏处,就是启动慢。微信里启动小程序速度看着还行,其实是微信在启动小程序之前,就已经提前初始化了小程序运行环境。

即便是排版引擎,ui库好用吗?

不管是rn还是flutter,有一个设计,很不中国化。它们在iOS和Android平台上,使用2套ui库。比如flutter,在iOS上写一个button,要用CupertinoButton,是iOS风格的控件,在Android上则要用RaisedButton,是Material风格的控件。rn也是如此,它的官方说法是:learn once,write anywhere。它都不敢说:write once,run anywhere。因为它确实要求开发者写2套代码。

中国的开发者可没有这种习惯,中国的每个开发者,为了避免用户换手机后不会用自己的app,都会使用中性的设计。就连微信Android版,底部的tab也是仿iOS而不是Material风格(Material风格是把底tab放在顶部的,并且左右滑动,微信曾经有这样一个临时版本,因为被用户吐槽,很快就下掉了)。

这种中外差异怎么造成的?

国外Android手机,其手机主界面就是强烈的Material风格。用户在Android主界面习惯的风格和使用方式,如果启动一个App后不是这样,会导致用户不会用了。Google也一再给Android开发者强调,App必须使用Material风格。这其实也是一个防止用户切换脱离Android生态的策略设计。所以国外开发者的App,Android上都会遵循Material风格,当然,这种Material风格的App是上不了Apple的Appstore的。

这就导致他们默认就是要写2套ui的,所以rn和flutter都是iOS、Android各自1套ui控件。但在中国,我们的国产Android Rom,根本不是Material风格,很多rom以仿iOS体验为卖点。所以中国的App,全都是贴近iOS的中性风格,中国的用户换了手机,不管是手机os本身,还是App的使用,都不会造成切换障碍。

rn和flutter这种“跨平台”排版引擎,其跨平台性,对于中国开发者而言,又打了折扣。其实类似小程序那样的ui风格,是能够良好的跨iOS和Android的体验的,不管用什么手机,打开小程序都不会觉得有问题。uni-app默认也是这种通用ui风格。uni-app的开发者只需要写一套界面ui,就可以适应不同手机的用户,真正的 write once,run anywhere。

动态性

webview、rn/weex,都有一个特点,可以远程动态载入js代码,可以更新本地的js代码。前端开发者认为动态性是天经地义的,但其实flutter并不支持。flutter是有编译优化概念的,如果它提供动态性支持,会影响它的性能。业内有些开发者,改造了flutter,用一个独立的v8/jscore来加载动态js代码,去操作flutter布局引擎的渲染。好像还有些人在追捧这样的方案,简直是闲得蛋疼。flutter本来没有跨环境通信的问题,结果又弄了一个js引擎进来搞出了通信问题,造成性能下降,还把包体积增加了很大,还不如直接用rn/weex。除了flutter,rn/weex/uni-app都可以动态热更新。

跨平台排版引擎和跨平台应用开发引擎的区别

有些人说他们的App用rn/weex、flutter。但是具体用它们做了什么呢?是整个App用了它们,还是某个页面用了它们?

一个页面跨平台,和一个应用跨平台,是完全不同的2个概念。webview、rn/weex、flutter全部是渲染引擎,webview因为HTML5的发展,还算是多了一些能力比如位置服务、多媒体等。而rn/weex、flutter真的只是一个纯粹的排版引擎,没有任何原生能力。如果一个原生应用里,某个不涉及原生能力的界面想跨平台,那么这几个引擎都可以,并且flutter的性能最高。所以能看到一些公司尝试把App中的个别原生交互较少页面使用flutter实现。但如果一个完整的应用,想用跨平台工具开发,那就不是排版引擎的范畴了,它需要应用开发引擎。什么是跨平台应用开发引擎?不但排版部分要跨平台,开发API也要跨平台。应用开发离不开os或三方sdk的能力调用,如果是单纯的排版引擎,一旦涉及os能力和sdk调用,就必须iOS、Android的工程师配合,编写不同的原生代码整合在一起。这就不跨平台了。

Airbnb曾是React Native 框架的倡导者和开发者代表。但他们于2019年正式发公告,弃用了react native。原因是什么?很简单,react native并不能提升Airbnb的开发效率,反而降低了他们的效率。“本来我们可以只维护Android和iOS两套代码,但现在我们要维护三套(指多了一套react native的js代码),这让我们很疲惫” -- aribnb开发者选用跨平台开发引擎,本来是为了提高效率、降低成本。Airbnb正是在实践了几年后,发现rn根本无法实现他选用跨平台引擎的初衷时,无奈放弃了rn,用原生开发重写。要想真的提升开发效率,降低开发成本,那么跨平台开发引擎,需要提供一个完整的应用开发平台,包含所有常用的应用开发能力的跨平台。在不常用的部分,提供插件市场以及免原生介入的插件使用方式。在react native、flutter的社区,也有不少三方提供的原生插件,但是连Airbnb这样的国外开发者对此都不满意。更何况对于很多中国开发者常用的场景,其对应的插件的质量、跨端性都难以商用。更麻烦的是如果你不会原生开发,就没法把这些插件与你的前端代码集成起来。

uni-app,它的设计目标不是跨平台排版引擎,而是跨平台应用开发引擎。所以uni-app的排版部分,可以选择小程序强化webview引擎和weex引擎,可根据自己的需求切换。而能力层面,uni-app提供了htmlplus API、Native.js、插件市场,解决了原生能力js化的问题。uni-app让开发者真的不用懂原生开发就能做出完整的跨平台应用。遇到极个别的需求,开发者也可以去插件市场找人订做一个原生插件,自己仍然使用js来集成,仍然可以云端直接打包。

生态

任何开发引擎,都离不开生态。对于国外的开发者,rn、flutter的生态肯定比uni-app好,比如facebook登陆分享、Google地图等。

但对于国内的开发者,那是反过来的,中国开发者需要的全端推送(UniPush集成了iOS、华为、小米、OPPO等众多原厂推送)、各种国内登陆、支付、分享SDK、各种国内地图、各种ui库、以及Echart图表等,都是在uni-app体系里,这方面生态可比rn、flutter丰富多了。uni-app的插件市场有数千款插件,不能说应有尽有,但确实是最丰富的跨端开发框架生态了。

另外,uni-app的生态还比其他竞品强在如下方面:

  • App和H5提供了renderjs技术,使得浏览器专用的库也可以在App和H5里使用,比如echart、threejs等
  • 兼容微信小程序 JS SDK,丰富的小程序生态内容可直接引入uni-app,并且在App侧通用
  • 兼容微信小程序自定义组件,并且App、H5侧通用

这些丰富的生态兼容,是flutter无法享受的。rn14年就正式建立社区,相对uniapp更早,其生态更丰富,但是由于很多涉及本土化不足,因此并不存在比uniapp丰富很多的现状,目前三者生态成熟度react native>uniapp>flutter。

技术学习成本和难度

rn,要求开发者学习react,要求精通flex布局,要求原生开发协作。

flutter,要求开发者学习dart,了解dart和flutter的API、要求精通flex布局,要求原生开发协作。

weex已经内嵌到uni-app中,就不单独提了。uni-app,要求开发者学习vue,了解小程序。

很明显uni-app的学习成本太低了,它没有附加专有技术,全部使用公共技术。

学习成本和难度,直接意味着:开发成本、招聘成本、上线速度、上线风险。

比较内容

Flutter

RN

Uniapp

平台实现

通过Dart虚拟机编译成机器码

Virtual Dom映射到原生View,ART虚拟机编译成机器码

浏览器内核渲染

绘制引擎

Skia

JS+Skia/OpenGLES

JS /weex

使用语言

Dart

React

Vue

上手难度

一般

容易

框架程度

较重

较重

较轻

社区

丰富谷歌力捧

丰富FaceBook支持

丰富vue社区庞大

软件发布

支持热更新

支持热更新

支持热更新

性能

一般

一般

其他端的跨端性

flutter是支持web技术的。但都是仅限于普通界面排版,涉及定位、摄像头、相册什么的,是要单独写代码的。另外flutter的H5版,嗯,作为中国开发者,你不会想要一个如此浓郁的Material风格的H5版的。。。更何况这个Material ui库大的很,编译出来的H5版要十几M的体积。

rn和uni-app的H5端是包含完善的能力引擎的,丰富能力都可以直接跨端使用,风格也是跨端风格。uni-app的H5引擎体积只有1百K,gzip后只剩下30k(不含vue、vue-router),比其他工具的引擎体积要小的多。rn的引擎体积稍大,但是技术最成熟。另外,中国离不开小程序目前flutter官方都不会支持小程序,由于架构差异太大,flutter在小程序方面的应用相对比较匮乏。反之uni-app则可以一套代码,同时编译为iOS、Android、H5、微信小程序、支付宝小程序、百度小程序、头条小程序、QQ小程序;rn则有成熟如京东开源taro框架实现多端小程序实现(微信小程序、支付宝小程序、百度小程序、头条小程序)。这一句rn和uniapp胜出。

结论

如果你是一个资源充沛的大公司,原生App中部分不要求动态更新、也没有太多原生交互的页面,可以尝试使用flutter实现。如果你的技术团队js基础较好,有一定的前端开发经验,或者对于react框架相对比较熟悉,建议选择rn框架。如果都不满足,那么可以考虑uni-app选用了原生渲染,那App的性能足够好,且你得到了切实的开发效率的提升、成本的下降、快速和低风险的上线。

【详细】三种主流跨平台技术探讨相关推荐

  1. 三种主流RIA技术之争,你该如何选型?

    前几天听说Adobe发布了用于Flash Player的RTMP(实时消息协议).乍一看,好像是一个不错的东东.号称有如下优点:支持高性能地把数据(主要是音频.视频)PUSH给Flash Player ...

  2. 三种主流无线同屏技术介绍(Miracast、DLNA与AirPlay技术)

    不知道大家对无线同屏技术有多少了解,当这种技术普及的时候,我想我们的工作与生活又会方便很多吧!下面是目前三种主流同屏技术的介绍: 目前这种将终端信号经由WiFi传输到电视.电视盒的技术有三种:DLNA ...

  3. Java处理XML的三种主流技术及介绍

    Java处理XML的三种主流技术及介绍(1) 2012-08-15 10:44 顾彬/冯晨/乔彬 IBM developerWorks 我要评论(0) 字号:T | T XML (eXtensible ...

  4. 三种主流的Kubernetes部署方式

    [译者的话]本文分析介绍了三种主流的Kubernetes部署方式,为广大Kubernetes的使用者提供了很好的参考借鉴. [烧脑式Kubernetes实战训练营]本次培训理论结合实践,主要包括:Ku ...

  5. 当前java web架构形式_关于三种主流WEB架构的思考

    关于三种主流WEB架构的思考Haohappy  haohappy AT msn.com转载请注明来源: 做WEB好几年了,各种语言和技术都稍有涉猎.今天心血来潮,突然想总结一下.其实不论什么技术,什么 ...

  6. 虹科分享|三种主流工业以太网概述及其应用

    关于工业以太网(industrial Ethernet),你知道多少?了解它和以太网的不同之处吗?接触过的产品是否有用到工业以太网接口?它的发展趋势你注意到了吗?这篇文章,带你了解工业以太网的起源.三 ...

  7. 三种主流工业以太网概述及其应用

      关于工业以太网(industrial Ethernet),你知道多少?了解它和以太网的不同之处吗?接触过的产品是否有用到工业以太网接口?它的发展趋势你注意到了吗?这篇文章,带你了解工业以太网的起源 ...

  8. 移动GPU三种主流架构优缺点浅析

    导读: GPU是Graphic Processor Unit的简称,顾名思义就是图形处理器. GPU的概念最早是从图形工作站发展而来,从90年代的个人电脑普及开始,GPU迎来了其大发展的时代. 在90 ...

  9. 三种数据交换技术的比较

    三种数据交换技术的比较 http://book.51cto.com  2007-04-23 17:55  王达  电子工业出版社  我要评论(1) 摘要:本章主要介绍局域网.广域网,以及OSI各层主要 ...

最新文章

  1. 悉尼大学陶大程:遗传对抗生成网络有效解决GAN两大痛点
  2. Selenium2学习(八)-- 操作元素(键盘和鼠标事件)
  3. 2014 ACM省赛总结
  4. 【转】Docker 运行时资源限制-内存memory、交换机分区Swap、CPU
  5. 85元一个万能工具箱,配齐24种螺丝刀+扳手,媲美德国工艺,家庭必备
  6. C++中字符型和整型的关系
  7. 【渝粤题库】陕西师范大学164104 网络财务管理 作业(高起专)
  8. 动态添加input_前端提效必备:动态模版生成
  9. python 单链表节点怎么快速定义_线性表链式存储结构之单链表
  10. 漫画:去掉一个数,如何让剩余的数乘积最大?
  11. 基于visual Studio2013解决C语言竞赛题之1033数字交换
  12. [13年迁移]公司服务器坏了,无聊按面向对象的方法分析下javascript的空值和假值...
  13. 额外域控制升级为主控制域
  14. 小程序开发工具代码保存编译后,程序没变
  15. 教你百度网盘文件转阿里云
  16. 行业集中度数据(2000-2020年 )
  17. ASEMI场效应管12N65参数,12N65规格书,12N65特征
  18. 用友u8服务器优化,用友U8erp软件运行的性能优化方案图文教程
  19. AVPro Video
  20. 爬虫,第十次实战之线程池(梨视频下载)

热门文章

  1. linux怎么找回普通用户密码,Ubuntu Linux系统密码找回
  2. Intellij IDEA的永久破解网站
  3. 微信公众帐号开发教程第2篇-开发模式启用及接口配置
  4. DebugView在win7下没有输出内核信息解决办法
  5. soot中基本的对象
  6. 嵌入式数据库架构特点
  7. 实训报告万能模板计算机专业,计算机专业实习报告模板
  8. 随心测试_Python Se_005鼠标悬停操作
  9. ZigBee学习之11——MAC层API解读2
  10. 【工具】hadoop国内下载镜像