我不认为Flutter比React Native好
作者 Jamon Holmgren 译者 核子可乐
Jamon Holmgren是一家软件开发公司的创始人兼CTO,拥有超过25年的编程经验,同时也是React Native的核心成员,维护着几个开源库。在这篇文章里,他试着尽可能公平地从多方面去讨论Flutter和React Native的优劣势。本文仅代表他个人观点,希望能为读者带来收获。
作为目前人气最高的多平台移动应用框架,Flutter与React Native可谓难分伯仲。关于二者谁更胜一筹的争议也从未止歇……开发者纷纷站队,应用交付也只选其一。那么,到底谁更强?
取巧的回答是,“具体要分情况。二者各有利弊,选谁不选谁、要看具体取舍。”
但这样的回答说了等于没说。废话文学解决不了问题,正面对线才是群众们喜闻乐见的场面。所以,咱们就整点直接的、刺激的,聊聊Flutter和React Native谁更强。
这话题,重要吗?
其实不重要,但不重要不代表没意思:性能、开发者体验、Dart与JavaScript、本机集成、标准库等等都是很有意思的话题,都值得拿来一聊。
有些朋友可能觉得这篇文章有点标题党,别着急,我会在后文中以更细微的方式深入探讨论断背后的种种细节。
现在咱们直入正题:这话题,重要吗?
说重要也重要,对于一家打算开发新应用的企业来说,以下几个问题就是无法回避的现实考量:
招聘
现在,招聘开发者可谓困难重重。技术岗位的工资不断上涨,市场供应却相当有限。想来的人看不上、看上的人不想来,难得很。
Flutter开发者的群体特征,可以用热情和优秀来概括,也体现出整个技术社区的整体倾向。但问题是,这类开发者数量不大,没法像Dart那样随招随有。所以,我们只能在企业内部不断培训,引导大家掌握Flutter。
另一方面,React Native开发者的规模就相当可观了,背靠的是声名极盛的JavaScript社区。JavaScript(及其变体TypeScript)堪称当前世界上最为流行的编程语言,而且参与者数量仍在快速增长。支持React Native的React.js也可以说是世界上最大的编码框架之一,甚至没有之一。所以,招聘工作虽然也是困难重重,但可供选择的开发者数量肯定比Flutter大得多。另外,React开发者也能比较轻松地转型成高效靠谱的React Native开发者。
共享代码、知识与开发者
除了招聘之外,决定Flutter和React Native谁更强的另一个重要因素,就是共享代码、知识与开发者的规模。
在软件开发领域,有什么是比代码好更重要的?那就是代码少。而削减代码工作量的最佳方式之一,就是在各种应用程序之间共享现有代码成果。这不仅能缩短初始开发周期,也有利于简化长期维护流程。
没准你的公司正在网站、Web应用程序或者服务器当中使用React.js,或者至少在用JavaScript。这种在React.js应用程序、Node服务器等场景之间共享代码的能力,正是React Native最引以为傲的资本——相比之下,Flutter就明显弱一些。
除了共享代码,React Native还能在Web、后端、iOS及Android团队之间实现知识共享。网上关于React Native、React和JavaScript的教程也是所在多有,这还没算上技术博文、StackOverflow问答等补充性内容。
另外,开发者也能在各个项目之间“反复横跳”,不用经过多少二次培训就能快速投身于时间紧、任务重的关键项目。
所以在React Native和Flutter二选一的交锋中,我们很难忽略上面这些基本事实。
那,其他因素呢?
是的,性能、开发者体验、可访问性、第三方库生态也都很重要。
而在这些方面,Flutter与React Native基本是拼了个五五开。Flutter在某些方面胜出,React Native也拥有自己的特定优势。所以除了能跟Web共享代码这一条外,二者在其他特定方面都属于势均力敌的状态。
开发者体验
Flutter团队(乃至整个Google)真的很擅长设计开发者体验。
Flutter的开发环境设置难度一般低于React Native。Flutter的热重载效果也比React Native的快速刷新好一些。它提供非常出色的部件调试、分析与检查工具,内置的端到端测试功能也比React Native的Detox好很多。Flutter的CLI堪称行业顶尖——我就特别喜欢其中的flutter doctor命令,允许开发者直接通过CLI管理自己的模拟器与仿真器。
Flutter的升级体验也更好,我们直接在现有应用程序中运行flutter create,它就能根据新版本重建所有内容。
与之相比,React Native的很多工具不像Flutter那样优雅完善。其中最让人难受的就是升级体验,最近几年用过React Native的朋友们应该对此深有同感。
当然,情况也在逐渐改善。微软的几位大佬就在之前的访谈中讨论过React Native工具与开发者体验的改进思路。
此外,Expo也确实极大改善了React Native中的开发者体验。使用Expo服务,大家不仅能够实现原版React Native中的一切功能,还将获得更好的升级体验与集成工具运行效果。如果不打算使用自定义本机代码,Expo Go则是一种无需编译即可与他人快速共享build的绝佳方式。总之,如果你正在使用React Native,千万别跟Expo失之交臂!
小总结:Flutter的开发者体验具有明显优势;React Native虽然正在迎头赶上,但还有很长的路要走——不过Expo的出现带来了一股强劲助力。
性能
软件框架的性能差异其实很难比较,更不用说像Flutter和React Native这样高度复杂的框架方案了。在大多数情况下,Flutter和React Native的速度都“够快”,如果开发者有能力做一点性能优化,那运行效果更是毫无问题。
不过从历史上看,Flutter的开箱即用性能一直要优于React Native。当然,防杠声明:我们都见过性能极差的Flutter应用程序和性能极佳的React Native应用程序,这里说的只是整体趋势。
二者的性能差异,主要源自异步React Native桥接器。但随着今年春季新架构的推出,它将被原生与JS代码间的并发通信所取代。此外,Hermes JS引擎也让许多关键性能指标更上一层楼。最后,Skia现已加入React Native全家桶,意味着大家可以在React Native用到跟Flutter相同的渲染器了——当然,仅限于需要流畅性能的位置。
小总结:Flutter在性能方面暂时小幅领先,但React Native新架构的推出有望快速缩小这方面差距。
统一的UI体验
Flutter使用Skia进行UI渲染,而且在所有平台上都提供统一的外观。这样开发者就能优化性能、自定义UI,有效摆脱平台天然特性的影响。
另一方面,React Native在iOS上使用UIKit,在Android上使用Android布局系统,在Web上用的则是DOM。这意味着虽然我们在构建应用程序外观时可以尽量强调相似,但实际跑在不同平台上时往往受到具体解释方法的影响。
人们对Flutter一直有怨言,批评它总在重新发明已经由平台自身解决了的各种问题,包括辅助功能、字体缩放等等。公平地讲,Flutter的方案效果不错(使用较低层级的内置平台hook),但毕竟是费了二遍劲;相比之下,React Native就总能或多或少依赖于平台提供的原语。
另外值得一提的是,Google开发者曾经表示不再将统一体验作为核心目标。这似乎跟Flutter的路线不太匹配。
小总结:如果大家觉得在不同平台上更好地匹配用户体验、要比提供跨平台统一体验更重要,那么React Native还是略微胜出。
原生集成
Flutter会把Dart代码编译成原生代码,再使用自身所谓平台通道(Platform Channels)将原生代码纳入酷炫的集成模型。它允许同步本机调用,也允许开发者使用Swift和Kotlin编写代码。Flutter的说明文档质量也很高,并提供开箱即用的测试与模拟等多种工具。无论你选择哪种平台,这里都提供大量模板,并通过Isolates实现了一流的线程支持功能。
而在React Native这边,原生集成就有一定的入门门槛了。另外,我们还得跟React Native桥接局限作斗争,原生集成的说明文档也不尽人意。
值得注意的是,新一代React Native架构直接去年了桥接器,全面引入了原生同步集成优势。所以升级之后,React Native的缺点已经不多了。
小总结:两大平台都具备完整的原生集成能力,但Flutter的原生集成工具更好些。
国际化水平
国际化/本地化(i18n)当然重要。Flutter就内置有i18n支持,所以不依赖于其他第三方。而React Native虽然缺少内置支持,但其中的第三方i18n支持确实越来越好。
小总结:没有输赢——两大平台在国际化方面都表现不错,但也各自存在一些局限。
内置导航(及更多)
Flutter在设计上比React Native更贴心,最典型的体现就是它带有自己的导航/路由解决方案。
导航属于特别适合集成到核心框架中的模块,因为它对大多数应用程序来说非常重要。大家可以想象一下不带路由程序的Next.js……那就基本废了。
React Native走的则是更为灵活的路线,允许开发者随意引入自己熟悉的导航解决方案。选项很多,但支持效果最好的是React Navigation和React Native Navigation库(有点遗憾)。
Flutter还提供内置的主题支持等功能。另一方面,作为React Native上的样板选项,Ignite也有自己的主题支持功能,唯一的区别就是这些主题并非React Native的内置主题。
Flutter这种内置路线的好处,开发者可以随意调整相应功能以匹配各个版本的框架特性。但内置路线也有缺点,就是一旦出现更好的范式,开发者只能祈祷官方支持团队能尽快更换那些更新、更好的解决方案。
小总结:Flutter有一定优势。带内置导航模块肯定不是坏事,不过React Native社区也提供不少出色选项。
Web支持
Flutter 2宣布将支持Web及其他平台。
但他们选择的Web方法只能说是“允许开发者在画布上绘制”,而非使用原生DOM。
这肯定会带来辅助功能和SEO方面的问题。还不止如此……总之,委婉一点讲,用Flutter开发Web应用程序应该不是首选方案。
值得一提的是,Flutter确实也提供HTML/CSS/DOM版本,只是用得没画布渲染器多。但即使如此,在这方面它也根本无法与React.js相抗衡。
另一方面,无论大家是用React Native开发Web应用程序、还是直接选择React.js,React Native都能直接共享代码。通过JavaScript/Typescript共享服务与模块,开发者能够轻松共享大量业务逻辑、数据模型等,并在Web应用程序中拆分并直接共享UI组件。总之,React.js是专为Web而生,一切设计都以Web开发为目标,这一点跟Flutter for Web有所不同。
小总结:React Native占据明显优势。虽然Flutter 2也在朝着这个方向迈进,但React Native在Web领域已经拥有巨大的先发优势。想要缩小差距,很难的啦。
第三方库
在典型的React Native应用当中,我们会用到大量最初专为JavaScript或React设计的库和工具,包括axios, mobx, redux, lodash, ramda, eslint, babel, jest, prettier, react-devtools, typescript, npm以及yarn等等。
这些都是Web和Node开发者常用的库。所以在社区合并之后,这些工具将获得两方面的贡献和改进,知识共享与互帮互助的氛围也更好。
另一方面,Flutter则主要使用量身定制的库。虽然市面上也有部分第三方Dart库可用,但社区规模远远不及JavaScript。
话虽如此,但Dart其实带有统一的格式化程序、测试、编译器、分析器/linter与包管理器,同时也是一种类型安全与空值安全的语言。所以在使用Flutter加Dart时,开发者可能很少需要再借助什么第三方库。
小总结:Flutter与Dart都提供不少高质量的内置工具,但React Native拥有显著的第三方生态规模优势。而且必须承认,Dart/Flutter这样的孤立社区基本不可能重现JavaScript/React这样的强大生态系统。
使用React Native与Flutter的公司
React Native的发展壮大离不开众多企业的不懈努力。除了Meta/Facebook之外,微软也在大力投资React Native项目开发。项目核心团队一直与微软开发者在各个方面上开展合作,微软一方还使用React Native重写了许多应用程序,并为其构建了大量工具和库。事实上,微软最近甚至宣布连Windows中的主Settings应用就有一部分是用React Native编写的!
除了Meta(Facebook与Instagram)和微软之外,React Native还得到了Coinbase, Shopify, Mercari, Discord, Pinterest, 特斯拉, 沃尔玛, Wix, Salesforce, NFL, MLS以及Uber Eats等大型组织机构的广泛使用。
Flutter的支持力量主要来自Google,而纵观整个发展历程,Google对项目的支持表现只能说是喜忧参半。另有一些企业也在使用Flutter,包括丰田、eBay与阿里巴巴,但大部分开发工作还是由Google亲自推动。
话虽如此,但Flutter在开放性、全面开源、社区的持续参与以及反馈驱动开发方面做得很好。与之对应,React Native给人的感觉就有点以自我为中心,一般优先考虑Meta/Facebook的实际需求,之后再把成果推向外部。但React Native核心团队一直在努力让项目转向社区驱动。
小总结:React Native占优势。这个问题比较复杂,涉及很多细小差别,这里就不过多赘述了。
动态更新(代码推送等)
很多项目其实并不需要动态更新,但不少企业客户倒是因为这个喜欢上了React Native,因为它能对应用程序进行动态更新、从而避过App Store和Play Store复杂的审批流程。Flutter这边就没有类似的设计,在未来发展路线图上也没提到。
小总结:优势在React Native。
所以,我们到底该用React Native还是Flutter?
具体要分情况。二者各有利弊,选谁不选谁、要看具体取舍……虽然网上关于这个问题总是吵得沸沸扬扬,但还就真没个确切的答案、二者的差异也着实不太明显。
前文已经提到,市场上的技术人才储备直接决定着招聘难度,这可能是具体选择时的首要考量因素。如果你已经拥有使用JavaScript/TypeScript的Web及后端开发人才,特别是已经在使用React,那么React Native肯定是更好的答案。
如果你站的是Java或者Android这队(掌握Java/Kotlin的开发者可以轻松上手Dart),而且/或者需要更统一、更流畅的UI,那Flutter的优势就体现出来了。虽然招聘难度也许更高,但Flutter至少还提供更好的开发者体验与性能表现。
总之,在抛开了“正确的废话”之后,现在大家又多了一点指导权衡思考的素材。
写在最后
这个话题着实敏感,稍不注意就要挨骂,所以我得再说几句免责声明。首先,这只是我的个人观点。我做的就是React Native咨询业务、而且与React Native核心团队保持合作,所以我不会说自己的观点有多么客观公正。但我确实做了不少研究,充分考虑到两大平台的业务合作现状,也在撰稿时参考了几位Flutter开发者的修改意见。他们也许不同意我的观点和结论,但我确实有认真考量他们的反馈信息。总之,我希望尽可能在文章中公平讨论这个问题。
我也不关注那些什么美学、优雅层面的问题,例如Dart和TypeScript的语法、或者JSX和Dart的功能部件结构谁更好之类。这些属于个人喜好问题,争来争去也不会有确切的结论,也不至于给框架的可用性带来任何本质影响。Dart和JavaScript/TypeScript之间当然有区别,但这又是另一个话题,不在本文的讨论范围内了。
最后,对本文观点持赞同或不同意见的读者,都不妨在留言中聊聊自己的看法。
原文链接
https://shift.infinite.red/flutter-is-better-than-react-native-fed10c92a768