flutter、rn、uni-app比较 ,到底哪家强?

前言

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

flutter最近比较热闹,毕竟是Google出品。html

但咱们不是炒做热点的媒体,也不是忽悠你交学费的培训机构,咱们做为实际的跨平台开发者,冷静的分析下这个东东。前端

flutter是Google为Fuchsia操做系统设计的应用开发方式。vue

Fuchsia OS要兼容廉价物联网设备,要求对硬件的消耗下降,而且为了不与oracle的java打官司,Fuchsia 使用了dart语言+flutter界面库的方式。java

从设计上来看,这套方案的性能确实够高。dart虽然属于大前端范畴,但dart是和java同样的强类型语言,这让dart虚拟机能够作不少优化,性能方面超出了js。react

dart曾经与typescript竞争,谁才是更好的js?但不幸输给了typescript,chrome也放弃了内置dart虚拟机的计划。css3

不过dart团队没有解散,几年后,他们借助flutter,再次出如今公众面前。c++

性能分析和写法的对比

flutter做为界面库(注意它只是界面库,dart语言是另外一个项目),它惟一要干的事情就是渲染界面。不像HTML5,flutter界面库连视频、定位等都没有,就是一个纯排版引擎,绘制文字、按钮、图片等经常使用界面控件。git

这个排版引擎的特色是简单、高性能。github

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

因此咱们要清楚,提高性能是有代价的,你究竟想要灵活丰富的css3,仍是想要固定flex模式排版,抑或是最简单但高性能的flutter排版?开发便利性和运行性能不可兼得。

同时咱们要明白,性能的差异,并非由于Google的chrome团队、Android团队的技术比同公司的flutter团队差。而是flutter提供的布局写法是被限制过的,解析快,因此渲染快。别忘了webview的排版引擎也是世界级工程师用c写的。

但经过这种方式提高性能的代价,就是布局复杂的界面时,flutter的代码嵌套的让人崩溃。

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

<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  
}

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,要求开发者学习react,要求精通flex布局,要求原生开发协做。

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

weex已经内嵌到uni-app中,就不单独提了。

uni-app,要求开发者学习vue,了解小程序。

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

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

另外,dart究竟值不值得学,是一个大问题。

Google的天才工程师也发明了go语言,它确实有不少理论优点,但实际上市场的主流,仍然是c和c++。

生态

任何开发引擎,都离不开生态。

对于国外的开发者,rn、flutter的生态确定比uni-app好,好比facebook登录分享、Google地图等。

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

其余端的跨端性

flutter和rn,都是支持web技术的。但都是仅限于普通界面排版,涉及定位、摄像头、相册什么的,是要单独写代码的。

另外flutter的H5版,嗯,做为中国开发者,你不会想要一个如此浓郁的Material风格的H5版的。。。

更况且这个Material ui库大的很,编译出来的H5版要十几M的体积。

uni-app的H5端是包含完善的能力引擎的,丰富能力均可以直接跨端使用,风格也是跨端风格。uni-app的H5引擎体积只有1百K,gzip后只剩下30k(不含vue、vue rooter),比其余工具的引擎体积要小的多。

另外,中国离不开小程序,rn、flutter官方都不会支持小程序,因为架构差别太大,国内三方也作不到把rn代码良好的编译为小程序代码。uni-app则能够一套代码,同时编译为iOS、Android、H五、微信小程序、支付宝小程序、百度小程序、头条小程序、QQ小程序。

结论

每种技术的诞生,有其背后公司的目的。

但凡没有明确公司战略的技术,除非是特别简单的技术,不然很难商用,由于为了商用要投入公司很是多资源。

flutter诞生的目的,是为了Fuchsia OS,是为了在下一个互联网大潮,即万物互联的物联网年代,提供一个相似Android在移动互联网位置的垄断性操做系统。

由于Google已经很明确不会在下一个时代使用Android+java的路线了。

至于在Android上去java化,那是Kotlin的使命,与flutter无关。

跨iOS和Android平台开发,这不是Google的战略目标。

但万物互联什么时候到来?Fuchsia OS什么时候流行?这在现实中是一个问号,在Google内部,也只是战略储备项目。

一个语言的流行,不是一件简单的事情,不是有优势,就会流行,它须要天时地利人和。

6年前咱们就知道dart比js更好,dart不该该消亡,但想成为主流技术,太难太难了。

一样咱们也知道go比c++更好,但go仍是起不来。

想靠flutter驱动dart流行是不现实的,甚至是反过来的。跨iOS、Android开发在国外不是主流市场,这点价值造就不出一个这么难建的生态。

因此dart可否流行,是要打一个大大的问号的,它可能会像go语言同样,叫好不叫座。

一个跨平台公司,应当是中立的。而flutter在这个位置上很尴尬,它是google出品的、同时跨iOS和Android的开发引擎。

若是这个引擎作大了,Apple会怎么看?那可不是像微信搞个小程序那么简单了,微信是中立三方,且只在中国。Apple不会让google的flutter在iOS上作大的。你们也都知道,即使是chrome,在iOS上也只能使用iOS提供的内核,容不得google在iOS上乱搞的。

写了这么多,最后总结下flutter与uni-app的比较:

flutter的相对优点:
    性能好一丢丢。比rn有优点,但比拥有bindingx和wxs的weex/uni-app,在实际开发中没有很明显的差距。
flutter的相对劣势:
    须要原生协做,维护3套代码,没法有效下降开发成本,提高开发效率
    嵌套地狱,代码难看难维护
    不支持热更新
    目前质量和成熟度很低,github上的issue有5k+,很容易掉坑里
    原生可视控件融合很差,好比webview、video、map
    ui库不适合国情
    学习成本高
    dart将来扑朔迷离

再总结下rn和uni-app的比较

rn的相对优点:
    rn的坑虽然比weex的少,但uni-app已经填了weex的不少坑。这方面差异不大。
    rn的生态虽然比weex丰富。但uni-app是反过来的,uni-app的国内应用生态丰富度超过了rn。
    rn的app冷启动比uni-app快。这个问题uni-app已经内部改进完毕,下个版本发布就能解决。
    rn是纯单页的,嵌入原生App比较灵活。而uni-app是应用总体的概念,若是要内嵌入其余原生应用的话,要求原生应用内嵌uni-app应用总体进来
rn的相对劣势:
    须要原生协做,维护3套代码,没法有效下降开发成本,提高开发效率
    不支持小程序,发布到h5也没法直接发
    ui库不适合国情,learn once,write anywhere
    学习成本高,用人成本高,不利于开发商下降开发成本
    rn是纯单页应用,若是一个应用的页面不少,用rn写会很崩溃,变量污染和干扰严重。而weex/uni-app支持多页面,页面之间上下文隔离,写页面较多的大型应用更合适
    另外react在中国的市场占有率远不如vue。这也是中国与国外不一样的特点状况。

贴个vue、react、react native的百度指数对比,不管整体量的差距,仍是发展趋势的下滑程度,能够明显看出react系在中国确实不行了。

中国的开发者,过去总会想:

小程序那套webview优化的技术,我能不能用到个人App里?如今uni-app已经为你解决了这个问题。
weex能不能坑少点,API和插件多点?如今uni-app已经为你解决了这个问题。

若是你是一个资源充沛的大公司,原生App中部分不要求动态性、也没有太多原生交互的页面,能够尝试使用flutter实现。但若是大范围使用,你也会遇到和aribnb同样的问题,维护3套代码还不如维护2套代码。

若是你开发uni-app选用了weex原生渲染,那App的性能足够好,且你获得了切实的开发效率的提高、成本的降低、快速和低风险的上线。

选择跨平台工具而不是原生开发,本质目的不就是为了成本和效率吗?能真正解决你本质需求的,就是uni-app。

欢迎扫码关注


原文:https://ask.dcloud.net.cn/article/36083

本文分享自微信公众号 - 前端迷社区(gh_c8466b051727)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索