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