希望从开发难度,生态及前景等方面进行考虑


每次回答这种问题都会引发「党争」,其实有些吃力不讨好,不过既然是「蹭」热度,那我就不从谁更优秀去评判,成年人不谈对错只聊利弊,就容我从另一个角度「瞎扯」。

我之前闲著蛋疼做过一个分析,大概分析了 53 框大厂的应用,其中明面上:

  • 带有 flutter 的有 20 款;
  • 带有 react-native 的有 22 款;
  • 带有 weex 的有 17 款;

国内大厂在移动端跨平台的框架接入分析 - 掘金?

juejin.im

怎么样,这个数据有没有给你带来不一样的感觉?其实做技术的很容易就陷入到「孕妇效应」里,做 rn 的认为 flutter 很小众火不起来,做 flutter 的认为 rn 要凉,毕竟大家圈子就那么大,而事实上现在 rn 和 flutter 在不同需求的市场上依旧过的滋润。

另外这里为什么说明面上呢,因为有一些 App 是使用动态化去下发动态库的,所以明面上看不出来。

就连 weex 都会有像 uni-app 的市场存在,另外现在阿里、位元组跳动和小米都已经开始在把 flutter pc 在推进到生产中使用,所以在我们「看不见」的角落都有它们各自的市场,只是我们选择了我们想看到的。

另外有时候企业会需要用新技术来维护前沿的技术形象,而员工需要新技术来创造 kpi 考核。

说到底语言谁更牛逼,框架谁更先进的争执不过是「技术人」自己的攀比,要生存要赚钱还是得有业务,所以实际上选择哪门框架的理由更多是:业务需要、面试需要、市场需要。从我的角度推荐:

  • 如果你的业务更看重热更新,你的方向和技术栈更贴近 React ,你的岗位更多是前端领域,那么你选择 react-native 会更适合,投入产出比更高。
  • 如果你是原生开发,你更看重性能和跨平台的兼容,那么 flutter 会更适合你,因为现在 flutter 的开发岗位更多和原生开发绑定在一起。

新框架的出现每次都会有人欢喜有人愁,说到底排斥的理由很大程度是因为未知和不理解。

我曾经举过一个有趣的例子,如下图所示是不同阶段扳手,可以看到:

  • 从 1 到 2 用户拧螺母需要准备的扳手数量减少了;
  • 从 2 到 3 扳手变得更加帅气有力,并且附带的「攻击力」也有所上升;

那问题来了:

一、既然有 2 这样便捷的扳手,那 1 这种扳手还有必要存在吗?

  • 答案是有的,因为 1 中的扳手性价比更高,在特点的场景下会更轻便。

二、那扳手 2 既然都满足大部分场景了,扳手 3 有必要存在吗?

  • 答案也是有的,因为 3 中的扳手更加「帅气「,同时从健壮的角度更可靠。

扯这两个问题其实是想表达:每个框架都有自己的市场,而你会选择哪种框架,主要还是前面所说的业务和工作类型决定。

当然这里还有一个有趣的误解:

扳手 2 升级后看起来比扳手 1 牛逼了,所以作为使用扳手 2 的我比使用扳手 1 的牛逼?

开发的鄙视链很多时候就是这么来的,但是从我的角度出发:牛逼的是扳手的制造者,而作为使用者,我们都是踩著别人的肩膀混口饭吃,在乎的不过是踩著谁更舒服而已。

当我批判一个框架时,我会想想我自己能不能造出比它更好的轮子?

最后,用好扳手的能力比选择扳手更重要,不管是 flutter 或者 react-native ,有的人也许只是写了 hello world 或者跑了个开源项目就开始跟风批判,很多时候框架的性能并不是我们的瓶颈,而使用的姿势和理解的程度才是我们的短板。

真实经历过有用 iOS 模拟器 debug 和我说 flutter 性能问题,而 debug 的 JIT 和 release 的 AOT 区别不用多说,官方都曾表示过 flutter 在 iOS 模拟器上不能使用 GPU ,所以用性能测试的场景有什么意义?

扯了那么多,结论还是那句话,在自己可以选择的条件下:react-native 更适合前端领域的开发者,flutter 更适合原生领域的开发者,同时还和你想面试的岗位和产品有关系。


目前来看我会选择用RN,但不会放弃对Flutter 的尝试。

没有其他原因,我已经有几个成熟项目的RN开发经验,所以线上选择我目前还是更倾向于RN。另一方面,RN的技术栈更具亲和力,没办法JS对于前端的亲和力太强了。

从目前生态来看,RN的生态显然更成熟些,一些问题基本都能找到解决方案,实在解决不了的通过桥接原生和自己修改源码也能解决。Flutter 目前我自己还没改源码的能力,所以还得继续研究下心里才有底。

尽管有些大厂在用Flutter了,但是很多和跟当年用RN一样,大部分是在一些详情页、个人页、社区模块在用,这样保证了可进可退,而且大厂的自研能力很强,一言不合就定制了,这对中小型公司来说就成本比较高了,相对来看小公司更依赖于生态完善性上了,所以在这里也提醒不要盲目追大厂的风。

Flutter 性能更好,而且跨平台上更彻底,这点是RN无法比拟的。RN 目前也在经历新版本的重写,未来发展成什么样也很难说。

无论选择哪个,深入去用了,你会发现跨平台其实也没那么美了,你不仅要懂js/dart还要有原生开发能力。一次编写,到处调试,各种环境的问题折腾的你会怀疑跨平台开发真的合算吗?

选择自己最趁手的能最快解决你的问题的技术栈,这是商业项目开发之本。


简单说一下 @Aego 回答中我觉得可以商榷的地方:

React Native 基于 JS-Native Bridge 的渲染方案有著没有办法弥补的先天缺陷。性能上优化到 60 fps 都比较成问题,更不用提以后广泛普及的 120 fps 的设备。

RN 之前的桥是完全用队列非同步的,JS 线程并不会阻塞 UI 线程的 vsync。

对于普通的动画场景,RN 在 17 年就给 Animated API 加了个 native driver 选项[1] ,这样 JS 线程只需要对动画做一个「声明式描述」,然后序列化后扔过桥一次就好,这样帧与帧之间的刷新都是 UI 线程直接跑,而不需要帧帧「过桥」让 JS 线程来做「插值」,所以刷新率什么的并没有什么影响。

可是旧架构问题在于,有一些强交互的场景(比如跟手拖拽)就需要同步阻塞更新怎么办?首先对于动画问题你可以看看 Reanimated [2] 这个库(btw Reanimated 2 已经是基于新架构得了),然后呢,我们来聊聊 RN 为了解决这个(以及其他)问题的「新架构」。

RN 在 18 年就提到了原有的桥架构不支持同步调用的问题[3] ,所以新架构的目的就是基于可同步调用的 JSI (JavaScript Interface)来重构原生模块(TurboModules)、渲染(Fabric)与初始化(比如创建 Timer、Event Loop)等,使得 RN 可以完全去掉「桥」。相关的资料比较零散,主要的资料可以看 RN 团队出去演讲的 youtube 视频,或者官方博客。社区文章尽管不一定准确但也可以凑合著看……(比如我随手搜到了一篇对社区文章的中文翻译[4])。

笼统得说,新架构的做法其实就类似大家熟悉的宿主环境(浏览器/Node)向 JS 引擎提供原生对象/函数的做法,JSI 在其中提供了这层宿主和引擎在编译期链接用的 FFI(foreign function interface),通信其实就是在 C++ 之间调用函数,宿主对象(C++ 对象)和 JS 引擎的堆(JS 对象)可以互相持有引用互操作,因此不但支持同步调用,而且也不需要像以前的桥那样在运行时序列化/反序列化,这带来的性能的提升大概能有两个数量级。以往的渲染(React VDOM 与 RN shadow tree 之间)其实也是反复过桥得,现在都不用了。

而且你会发现新架构中 RN 的核心部分基本都用 C++ 重写了,JSI 的两端都是 C++,Yoga 布局引擎本来就是 C++,与原生模块(JNI/OC++)的互操作部分现在是通过对 flow 做 codegen 来生成 C++。这一套零成本抽象下来,RN 的核心部分我觉得性能是不虚得。Dart 本身只是个带著 GC 和 RTTI 的 AOT,并不是系统编程语言,我不知道 Flutter 除了 Skia 之外的部分有多少是 C++ 多少是 Dart 得。

Flutter 的设计则是完全自绘组件,Skia 渲染引擎本质上就相当于游戏引擎的作用

Skia 是 Chrome/Android 都在用的二维图形库,Flutter 像个游戏引擎是真的。

从跨平台的 UI 一致性的角度上看,Flutter 可以做到完全的一致性,而 RN 在点击效果,阴影,甚至文本框之类的组件都无法做到不同平台间有著完全一致的行为。这点上对于有跨平台一致性强迫症需求的人来说,Flutter 几乎可以说是唯一选择。

Flutter 做得像游戏引擎有图形表达力强以及 self-contained 的优势,但是对于跨平台开发来说就「仁者见智」了,「完全的一致性」真的是我们想要的吗?iOS/Android 本来就有著不同的设计语言(滚动效果、点击效果、系统 UI 组件),有不同的 distribution 版本,并且也会不断演化。

你没看 Flutter 为了「模拟」原生效果只好搞了两套所谓的「平台物理」……然后系统 UI 组件还要全部自己造一遍主题轮子吗……Flutter 的 iOS 主题美其名曰 Cupertino,结果人家 Cupertino 真的改一版设计,你的轮子一下老了一代又要重新画了,委屈不委屈……(其实现在的看起来就挺过时挺惨得……)要不是你们 Mountain View 钱多人多真的烧不起啊。

RN 的哲学(官网博客[5])的第一点就是「要足够 Native」,所以才用了 binding 的方式,Cupertino 一声令下我们 Menlo Park 可能什么都不用做最多 binding 一下 API 就好……这种做法可以很好的融入平台,方便复用以往的基础设施,而且非常容易拓展新的平台支持:RN 的 Windows 和 macOS 版本也都不需要重新自己「画画」,而且还是大 Redmond[6] 做得呢……RN web 也是社区(Twitter)维护起来的,直接 binding 到 DOM 就完事了,跟以往的 web 基础设施在一起工作毫无问题。FB 内部还有其他用 React binding 的平台。

而且还有一点是,RN 是真正的开源社区活跃,像 Releases 什么都是社区在做,而 Flutter 就比较「吃 Google 饭」了……天哪你知道 Flutter 砸了多少人进去,RN 才多少人吗?只能说 Google 真的钱多,像 Flutter 的 Hummingbird(Web Support)要做起来真的是一件相当吃力不讨好的事情,真的钱多。

当然如果仅从个人小项目,对于性能要求不苛刻的情况下,确实 TypeScript 比较 Dart 还是有一些语言上的优势,对于前端开发者来说可能更好上手一些。

理论上说,Dart 2 改成静态类型有理由做到更好的性能,Dart 团队也非常有实力,不过:

  1. 我确实从来没有看到过任何像样的数据可以证明「Dart 性能确实比 V8/JSC/Spidermonkey 这些 JIT 的 JS 引擎性能好」,欢迎拿数据打脸。
  2. 如果考虑 iOS 平台上 Dart 可以做 AOT 而 JS 只能解释,那么 Dart 在纯运算("number crunching")来说没优势才是怪了。不过,这些性能能转换到多少 App 的体验就有待商榷了,毕竟 Dart 对 Flutter 可能是大头,而 JS 对 RN 只是一种「轻量脚本」方案,并不承当主要的计算任务。

但 Dart 语言由于有丰富的语言特性(比如 extension)

你认真得?要不是劈柴砸钱 Flutter 这玩意早凉到不知哪里去了。以前怎么从没见人用呢,Flutter 一出来你们反倒吹起语言来了?

Dart 是要特性没特性,要品味没品味。评论区说得好,狗家的语言都是「实用主义、大道至简」吧反正唉……没有正经学过点编程语言理论的不要来给我反驳这条,最烦的就是你们 :)

参考

  1. ^Using Native Driver for Animated https://reactnative.dev/blog/2017/02/14/using-native-driver-for-animated
  2. ^Reanimated https://docs.swmansion.com/react-native-reanimated/
  3. ^State of React Native 2018 - Architecture https://reactnative.dev/blog/2018/06/14/state-of-react-native-2018#architecture
  4. ^React Native 架构演进 https://zhuanlan.zhihu.com/p/142704512
  5. ^React Native Team Principles https://reactnative.dev/blog/2020/07/17/react-native-principles
  6. ^https://microsoft.github.io/react-native-windows/


https://t.cn/A62xuaBz 我们公司产品,完全用flutter写的

我们在18年完成了第一版客户端,用的的dcloud,为啥?别问,问就是小公司招不起原生。

受制于dcloud太多的性能问题以及各种使用限制(社区基本就是摆设,官方提问还要收3000大洋),我和当时的前端负责人以及老板讨论了前端的框架替代方案,当时前端4个人,3个人开始著手去调研,主要目标是rn,uniapp,flutter,weex。

我个人是后端出身,当时甚至想推荐xamarian。

调研的方向主要是从框架的控制项量、性能、社区活跃度、roadmap、背后靠山、语言难易度等纬度综合评价。

第一轮pk后剩下rn和flutter。

于是我自己去尝试了下,个人感觉,dart远比js来得优雅,其次dart算得上是一门比较现代的语言,吸收了不少高级语言特性,又不失灵活。flutter为了更好的迎合前端,放弃了晦涩的mirror库,这个算是比较遗憾的事情。

放弃rn有个主要的原因还是在性能上,当时为了做im,我们测试了各种控制项在大数据量的情况下的载入情况,rn是完败给flutter的。

在经过2个月左右的调研和demo后我们最终还是选择了flutter。

当然对著那5000+的issues当时是很担心的。

过程中也遇到不少坑,好在通过设计调整和技术攻坚都解决差不多了。

重写客户端花了3个月时间,19年7月正式完成了版本替换,中间整个团队背负了非常沉重的压力。好在结果还是非常不错的。目前除了偶发性的安卓版本兼容问题,以及webview不少坑之外,其他问题也随著flutter本身版本升级以及社区各种大佬的解决方案逐一解决了。

我们后来还是招了2个原生做技术支持,主要是为了使用一些第三方控制项而作原生到flutter封装工作。

目前我们团队前端技术栈包含flutter,vue和原生,学习是痛苦的,但也是快乐的。前端的同学自己也清楚,掌握更多的技能技巧意味著什么。我们这个团队人不多,但技术氛围还是不错的,遇到困难还是会去不断尝试克服。

我觉得没法从单方面去评价2个框架或者2门语言孰优孰劣,更多的还是需要结合团队、项目、公司、地区的实际情况。,适合的才是最好的。


看现有资源:

如果是小团队,甚至单干,flutter可以尝试一下,现在酷安上的独立开发者,很多都转flutter了。如果有其他react的项目关联,rn也是不错的选择,虽然跟react不是一个东西,但是多多少少有些相近的地方。

对于工程实践:

flutter的优势在于,不用太熟悉现有h5系前端体系,弄个差不多的美工甚至不用美工,也能搞个像模像样的app出来。

react的优势在于有大量的社区资源和团队资源可以用,只要不是还停留在jq时代的前端团队,改造一下,也能开始撸app。

至于前景:

啥叫前景,做个项目,多说几个月就进入稳定期,用不著考虑前景不前景,项目有了盈利能力,上原生、上队伍、重构、重做都不是问题。项目不确定后续的话,怎么省成本、怎么快怎么来。

要是说到个人前景的话,都玩呗,flutter、rn,加上uni-app、h5之类的,越多越好,艺不压身。经验丰富的意思就是踩的坑多填的坑多,技能精通的意思就是吃过见过被蹂躏过。

如果只能把精力投到一种上,个人建议投flutter,性能够用,见效快,能跟风,吹牛都能多吹几分钟。


推荐阅读:
相关文章