前言
每当我们评估新技术时要问的第一个问题就是“它会给我们的业务和客户带来哪些价值?”,工程师们很容易对闪闪发光的新事物着迷,却经常会忽略这些新事物其实可能对我们的客户没有任何好处,反而只会让现有的工作流程更加复杂。
Flutter最近比较热闹,毕竟是Google出品。
但我们不是炒作热点的媒体,也不是忽悠你交学费的培训机构,我们作为实际的跨平台开发者,冷静的分析下这个东东。
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> <div class=redbox> smaple text </div> </div> <style> .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 } </style>
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参数。
或者,你可以这么理解,这是一个只有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引擎),从JS与Dart的比较上,性能稍逊一筹。但这不是主要问题,主要问题是,RN、Weex的JS引擎和原生渲染层是两个运行环境。
当JS引擎联网获取到数据后,通知原生视图层更新界面时,有一个跨环境的通信折损。同样,当用户在屏幕上操作原生视图层时,要给JS引擎发送通知,也会产生这个通信折损。
不过这种性能差别,在大多数场景中,用户是感受不到的。比较影响的场景,是跟手式的JS响应操作绘制帧动画。
这方面,Weex有个值得称赞的技术是 BindingX ,它可以预定义规则,让用户界面在原生层交互时通过预定义规则直接响应,而无需传递给JS层。在需要短时间内来回通信的场景时,可以使用BindingX这类解决方案。它的性能和灵活性比RN更强了一些。
说回来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库。
比如Futter,在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丰富多了。
其他端的跨端性
Flutter 和 RN 都是支持Web技术的。但都是仅限于普通界面排版,涉及定位、摄像头、相册什么的,是要单独写代码的。
另外Flutter的H5版,嗯,作为中国开发者,你不会想要一个如此浓郁的Material风格的H5版的。。。
更何况这个 Material UI 库大的很,编译出来的H5版要十几M的体积。
uni-app的H5端是包含完善的能力引擎的,丰富能力都可以直接跨端使用,风格也是跨端风格。uni-app的H5引擎体积只有100K,Gzip后只剩下30k(不含Vue、Vue Router),比其他工具的引擎体积要小的多。
另外,中国离不开小程序,RN、Flutter 官方都不会支持小程序,由于架构差异太大,国内三方也做不到把RN代码良好的编译为小程序代码。uni-app则可以一套代码,同时编译为iOS、Android、H5、微信小程序、支付宝小程序、百度小程序、头条小程序、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 VS Uni-app
Flutter的相对优势:性能好一丢丢。比RN有优势,但比拥有Bindingx的Weex/uni-app,在实际开发中没有很明显的差距。
Flutter的相对劣势:
-
需要原生协作,维护3套代码,无法有效降低开发成本,提升开发效率
-
嵌套地狱,代码难看难维护
-
不支持热更新
-
目前质量和成熟度很低,Github上的issue有5k+,很容易掉坑里
-
原生可视控件融合不好,比如webview、video、map
-
UI库不适合国情
-
学习成本高
-
Dart未来扑朔迷离
RN VS 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实现。但如果大范围使用,你也会遇到和Airbnb一样的问题,维护3套代码还不如维护2套代码。
如果你开发uni-app选用了Weex原生渲染,那App的性能足够好,且你得到了切实的开发效率的提升、成本的下降、快速和低风险的上线。
选择跨平台工具而不是原生开发,本质目的不就是为了成本和效率吗?能真正解决你本质需求的,就是uni-app。
推荐阅读
· Next.js和Nuxt.js的语法比较
· 新手React开发人员容易做错的5件事
· Chrome浏览器终可以对标签进行整理和分组了
· 7个很棒的JavaScript产品步骤引导库
· 2020年排名前11位的静态网站生成器
· 让你在2020年成为前端大师的9个项目
点个再看呗
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 如何评估一项技术是否值得长期投入
- Gartner:2018年最值得投入的十大安全项目
- 如何避免安全项目投入中的“黑洞”
- 您应该在哪里投入有限的测试工作?
- 是时候放弃tensorflow集群投入horovod的怀抱
- CoreOS Fest:Oracle加深对Kubernetes的投入
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
大数据时代
[英] 维克托•迈尔•舍恩伯格(Viktor Mayer-Schönberger) / 周涛 / 浙江人民出版社 / 2012-12 / 49.90元
《大数据时代》是国外大数据研究的先河之作,本书作者维克托•迈尔•舍恩伯格被誉为“大数据商业应用第一人”,拥有在哈佛大学、牛津大学、耶鲁大学和新加坡国立大学等多个互联网研究重镇任教的经历,早在2010年就在《经济学人》上发布了长达14页对大数据应用的前瞻性研究。 维克托•迈尔•舍恩伯格在书中前瞻性地指出,大数据带来的信息风暴正在变革我们的生活、工作和思维,大数据开启了一次重大的时代转型,并用三......一起来看看 《大数据时代》 这本书的介绍吧!