早上刷技术资讯看到 Shopify 公告的那一瞬间,我整个人是坐直的——React Native 全球最大的商业实践案例之一,押注六年之后宣布回到原生开发。从 2019 年前后把移动端主应用全面切到 React Native 以来,Shopify 一直是跨平台阵营最爱引用的“标杆”;如今这个标杆自己推翻了“跨平台更高效”的叙事,选择完全用 SwiftUI 和 Kotlin 把应用重做一遍。这则消息对做移动端的开发者来说,不亚于一次小规模地震。
作为一个在移动端和跨平台方案里折腾了多年的开发者,这篇文章我不想写新闻复述,而是想聊聊几个真正重要的问题:React Native 到底哪里让 Shopify 不满意?为什么是“六年”而不是两年或十年?Shopify 的转向对普通创业团队到底意味着什么——是不是我们也要放弃跨平台?技术原因、架构演进、团队决策和选型建议,我会一次性说完。
1. 先说清楚事件本身:Shopify 的“主应用”为什么会掉头
1.1 从 2019 到 2024:一段完整的技术栈生命周期
2019 年前后,Shopify 开始在移动端应用里大力引入 React Native。当时跨平台方案里 RN 是绝对主流,Flutter 还没有大规模进入生产力环境,商业级案例最多的就是 RN。Shopify 在公开分享中多次提到,他们选择 RN 的第一原因是团队复用:Shopify 的 Web 端前端几乎全是 React 技术栈,移动端再用 React Native,前端工程师可以在 Web、iOS、Android 三个平台之间自由流动。听起来非常合理,也确实是驱动很多大厂选择 RN 的核心逻辑。
到了 2024 年第四季度前后,Shopify 对外确认,正在把核心移动应用逐步迁移回原生技术:iOS 侧全面转向 SwiftUI,Android 侧全面转向 Kotlin 和 Jetpack Compose。从外媒报道看,这一步不是小修补,而是“推倒重来式”的架构级手术。根据 Shopify 技术博客的公开数据,仅 iOS 应用里的 React Native 相关代码就已经达到百万行级别。这个数字意味着,迁移工程不是换一两个模块,而是要把数据层、渲染层、依赖体系全部打散重来。
六年时间,恰好是移动端技术栈一个完整的生命周期:技术选型时,业务还在起步,需要的只是“快速覆盖双端”;六年后的业务体量和用户体验要求,则完全换了一副面貌。这个生命周期里,不是 RN 突然少了什么,而是 Shopify 的业务坐标原点和用户体验标尺彻底变了。把六年时间放在一起看,你能看到一条非常清晰的技术债演化曲线:从最初的性价比红利,到中期的隐性维护成本,再到后期的性能天花板与迁移必然性。
1.2 这不是第一次:Airbnb 早在 2018 年就“撤离”过
很多人不知道,Shopify 并不是第一个“从 RN 撤退”的知名互联网公司。早在 2018 年,Airbnb 就发布过一篇震动业界的博客,详细复盘了他们为什么放弃 React Native、回归原生。Airbnb 的理由放到今天依然不过时:RN 在一些核心页面的性能和体验达不到 Airbnb 的标准;跨平台代码复用的比例并没有想象中高;为了维护 RN 基础架构投入的人力,甚至已经与维护两套原生代码相当。
Airbnb 之后,业内对 RN 的态度出现了一次大分化:一部分团队觉得“是大厂自己的问题,我们小项目用 RN 还是很香的”;另一部分人则开始重新审视跨平台的成本收益模型。Shopify 的六年大实验,某种程度上像是把 Airbnb 的话又完整验证了一遍。但这里必须强调:Airbnb 和 Shopify 都是“性能敏感型、体验极致型”的超级 App,他们的门槛不能直接套用到所有项目上。同样是放弃 RN,动机和后续路径却可能完全不同,这也是很多技术讨论里最容易失真的地方。
2. React Native 让大厂“用不下去”的真实痛点:从启动白屏到架构瓶颈
2.1 启动白屏问题:为什么用户会盯着空屏幕三秒
“react native 启动白屏”这个热搜词背后,是无数 RN 开发者的痛。很多 RN 应用冷启动时,用户会先看到一段空白页面,原因在于 RN 的启动路径和原生完全不同:原生应用冷启动后,系统直接创建原生页面,立即开始绘制第一帧;而 RN 应用需要先加载 JS Bundle,接着初始化 JavaScript 引擎(当年 Android 上用 JSC,后来有了 Hermes),然后在原生容器里创建 RootView,再执行 JS 侧的业务逻辑,让 JS 计算出第一帧视图树,最后通过 Bridge 或 JSI 交回原生层渲染。
这一串动作,在高端旗舰机上可能只要两百毫秒,跑不到“白屏”的感知阈值;但在大量中低端 Android 机型上,延长到几百毫秒甚至一秒以上是家常便饭。对于电商 App 来说,用户从点击图标到真正看到商品流,内心预期是“秒开”,任何一段空白时间都在消磨购买欲望。Shopify 做的是千万级交易量的购物 App,白屏时间对 GMV 的影响可以用真金白银来量化——这个问题不是靠打补丁能解决的,它嵌在 RN 的底层执行路径里。
新架构出现后,白屏问题有所缓解,Hermes 引擎、Bundle 预加载、脚本本地化都是有效的优化手段。但这里有个非常反直觉的事实:RN 团队做性能优化时,需要把大量精力花在“理论上应该由框架层兜底”的事情上,这本身就说明框架的默认路径偏离了原生标准。对 Shopify 这种体量的玩家,与其纠结怎么把 RN 优化到接近原生,不如直接用原生把事情做对。
2.2 Bridge 架构的通信税:一个被低估的性能杀手
“Bridge”是 React Native 旧架构的核心设计:JS 线程和原生线程之间,所有通信都要通过这座桥转一道手。过程中,数据要被序列化成 JSON,跨线程传递,再反序列化。如果页面高频触发 JS 与原生之间的交互,这种序列化、反序列化开销就会积累成肉眼可见的卡顿。
举个电商场景:一个商品列表页,手指快速滑动时,列表要在很短时间内渲染大量行,每一行的图片加载、埋点上报、状态变更都可能触发 Bridge 调用。在低端机上,一旦 Bridge 队列积压,UI 响应就会出现一顿一顿的感觉。这在纯原生实现里几乎不会出现,因为原生层直接操作 UI 对象,不存在“翻译官”的效率损耗。
RN 的 Fabric 新架构用 JSI(JavaScript Interface)替代了 Bridge,让 JS 可以直接持有原生 C++ 对象的引用,性能上限大幅提升。问题是,新架构的完备度爬到“可生产”状态花了太长的时间,第三方库的适配又是一场漫长的等待。对大厂来说,与其等待框架的“新版本救赎”,不如换到已经高度成熟的原生体系。这是一种典型的工程功利主义:稳定大于潜在好处,确定性胜过高上限。
2.3 依赖生态的“地雷阵”:版本升级是一场大手术
RN 开发江湖流传一句话:“升级一次 RN 版本,等于把项目重做一遍。”虽然夸张,但很说明问题。RN 的版本之间经常有 Breaking Change,社区第三方库的兼容速度跟不上,有些热门库甚至在 RN 新版本发布后数月都没完成适配。升级 RN 主版本时,经常发现某个核心依赖的 Android 端还没适配,iOS 端却已经正常;或者相反,这种分裂让双端同步升级十分痛苦。
我还要补充一条技术分享里很少说的经验:RN 项目的依赖图非常庞大,一个中型 App 动辄上百个 npm 包,每个包都有可能引入原生代码,最终编译期和运行期的风险都高度不可控。当你要求应用达到对标原生的质量时,RN 的“生态丰富”反而容易变成“依赖地雷”。排查一次崩溃,可能要从 JS 层一路挖到原生层,中途还要穿过无数个第三方包的内部实现,技术债的排查链路被拉得很长。对比原生开发,Xcode 和 Android Studio 的依赖管理相对集中,出问题时定位链路短得多。
2.4 长列表、动画与电商核心场景的极限
电商 App 最核心的场景,对跨平台框架来说是最苛刻的“照妖镜”:商品列表要丝滑、详情页要支持复杂的图片轮播、购物车要处理大量状态变化、促销活动页面还要有各种动效。RN 的 VirtualizedList 在数据量大的情况下,内存控制和复用效率不如原生 RecyclerView 和 UICollectionView。虽然社区有 FlashList 等优秀组件,但优化到极致后,和原生之间仍然有一截差距。
动画方面,RN 的 Animated/Reanimated 已经很强,但 JS 驱动的动画在复杂交互动效面前依然不如原生动画系统天然流畅。iOS 的 UIKit 动画和 Android 的 Material 动画都有大量系统级加速支持,RN 在这种场景下总是要额外付出努力才能追上。对 Shopify 这种把每个帧率、每次滑动跟手度都当作商品体验一部分的公司来说,RN 的表现追不上原生,这就是放弃它的最实际理由。你可以在小工具 App 里容忍偶发卡顿,但在一个承载真实交易的核心购物流程里,你很难容忍。
3. 六年的技术债:Shopify 是如何一步步走到“必须换”的临界点
3.1 当初为什么选 React Native:性价比式入场
现在回头看 Shopify 在 2019 年做 RN 选型,这是一个非常合理的性价比式决策。Shopify 是做 Web 起家的技术公司,前端技术栈以 React 为主。当时移动团队需要快速把双端 App 推向市场,而完全组建两个原生团队的成本高得吓人——iOS 和 Android 各自都要配套架构、QA、发布流程。选 RN,一套代码两处出包,前端工程师可以直接上手移动端开发,这种“人才复用 + 迭代速度”的红利,在当时几乎是降维打击。
更不用说那时 RN 正处在上升期,社区热度高,各种开源组件和中间件都非常丰富。对一个还在跑马圈地的电商平台来说,移动端速度就是商业生命线。RN 的短板在当时看来是可以忍受的,毕竟第一优先级是快速上线、覆盖用户,而不是把每一帧都打磨到极致。任何一个有经验的工程师都能理解这种选择:你不可能用一个重型方案去启动一个还没验证的战场。
3.2 业务量爆炸之后,移动端从“渠道”变成了“主战场”
但六年后的 Shopify,已经完全不是“上线一个 App 试试水”的状态。过去几年电商线上化进程加速,Shopify 的移动端购物占比持续上升,到 2024 年移动端贡献的收入已经成为核心来源之一。移动端不再只是一个“购物入口”,而是商家的“收银台”、营销的“落地页”、用户忠诚度的“主阵地”。
当业务量级从百万用户涨到千万级日活时,技术选型的标尺会陡然收紧:启动时间每慢 100 毫秒,都可能对应一个可见的转化率损失;崩溃率每升高千分之一,都会导致大量客诉和退款。Shopify 在公开分享里曾直接点出,他们的购物体验中有大量对延迟和掉帧敏感的交互——比如商品图的快速缩放、购物车数量变化时的动画、结算流程的流畅性。这些交互在原生体系里天然是顺滑的,在 RN 里则需要不断挑战性能边界。
六年的时间,业务规模和业务地位都变了。当移动端只是渠道时,RN 的性价比最高;当移动端成为主战场,体验的每一点瑕疵都会直接变成商业损失,原本的性价比模型就被彻底推翻了。用一句直白的话说:当你的命脉业务开始依赖移动端,你就得为移动端掏真金白银的现场成本,而不是选一个“差不多”的方案。
3.3 技术债的复利效应:初始化收益并不会让你安然渡过增长期
为什么“六年”这个时间点很微妙?因为第一年选型时省下的成本,会在第三四年以另一种形式加倍还回来。RN 团队维护过程中,会不断遇到这样的循环:某个页面性能不达标,于是写一个针对性优化补丁;补丁引入了新依赖,新依赖又产生新 Bug;等 RN 升级时,补丁全部需要重新适配。这类补丁式负债会逐年累积,最终达到“维护 RN 版本所耗费的成本,已经与维护两套原生代码相当,甚至更高”的临界点。
Airbnb 当年的复盘里其实也提到了类似的逻辑。RN 的单次集成成本不高,但长期持有成本不低。这种成本是隐性且递增的:需要专门的 RN 基础架构组、需要持续跟进上游版本、需要为第三方库做兼容补丁、需要花大量时间做性能剖析。当业务体量不大时,这些成本还不明显;一旦进入增长期,开发节奏加快,每个技术债都会在紧要关头咬你一口。Shopify 用了六年走到这个临界点,和创业公司通常两三年就触及“要不要重写”的疑问相比,已经算非常能扛了。
4. 回到原生之后:确定性红利和双倍成本,哪个更真实
4.1 SwiftUI + Kotlin:Shopify 披露的迁移路线
根据 Shopify 公开的技术博客和开发者大会上的信息,他们的迁移目标很清楚:iOS 侧全面转向 SwiftUI,Android 侧全面转向 Kotlin 和 Jetpack Compose。这基本是现代原生的“标准答案”组合。为什么是 SwiftUI 而不是直接沿用 UIKit?因为 SwiftUI 是苹果力推的未来方向,声明式语法在开发效率上不比 RN 差多少,同时又有原生的性能底子;Android 这边的 Jetpack Compose,同样是 Google 力推的声明式 UI 框架。换句话说,Shopify 不是退回十年前的老路,而是拥抱了新一代原生技术栈。
有一点值得所有团队注意:百万行级 React Native 代码的重写,显然不是“某个页面重做一下”那么简单,而是要把数据层、渲染层、依赖体系全部打散重来。从组织架构上讲,这也不只是技术栈的切换,更是团队技能树的切换。一个真实影响是:原本精通 RN 的工程师要转型 SwiftUI 或 Kotlin,或者公司需要重新招聘大量原生工程师。大厂有资源做这种转型,但小团队在考虑跟随这个大动作之前,得先掂量一下自己的家底。
4.2 原生开发带来的是什么:更强的性能上限和更深的系统整合
回归原生,最大的红利是“确定性”:原生应用在启动速度、滚动帧率、内存占用、动画流畅度上,可以直接达到系统级的最佳状态,不需要绕一层 JS 到 Native 的桥。对 Shopify 的购物场景来说,这意味着结算流程可以更快、更稳,也意味着在关键路径上可以对每一个耗时做更精细的原生级优化。
另一个红利是对系统 API 的深度访问。电商 App 想尝试 AR 试戴、用 Core ML 做商品智能推荐、接入 Apple Pay 和 Google Pay 的深层支付流程,这些在原生体系里都是系统级能力,调用起来最直接。RN 虽然也能通过封装原生模块来使用这些能力,但每多一次封装就多一层维护成本和沟通成本。越往深水区走,原生的优势越明显。这也是很多团队从“跨平台 MVP”走向“原生旗舰”的经典路径:先用跨平台验证业务,再在关键战役切换原生。
4.3 别把“回归原生”理解成“跨平台已死”
写到这里我必须泼一盆冷水:Shopify 回归原生,根本不能证明“跨平台已死”。反例太多了——微软的多款核心 App 长期基于 RN,不少头部互联网公司的部分业务也还在 RN 上跑得很稳;Flutter 在桌面端和移动端的表现也越来越好。跨平台框架存在的意义,是让团队用更少人力覆盖更多平台、更快速地验证业务。对大量非性能敏感型产品,比如内容社区、工具型 App、企业内部应用,RN 和 Flutter 依然是极其正确、极其高效的选择。
更重要的是,技术选型从来没有“绝对正确”,只有“在某个时间点、某个团队、某种业务约束下的最优解”。Shopify 做了一次大型技术实验,实验结论只适用于 Shopify 自身的坐标——体量巨大、性能敏感、移动端即主战场。你若是拿这套结论去套一个刚起步的小团队,那就等于拿波音 747 的飞行手册去指导一个骑自行车的人。场景不同,答案必须不同。
5. 给你的技术选型清单:现在到底该不该用 React Native
5.1 被热搜刷屏后,先做一个冷静的比价模型
这两天“react native 启动白屏”“react native 教程”之类的热词被顶上来了,不少刚入门的朋友慌了:Shopify 都不用 RN 了,我是不是白学了?我建议你先做一个冷静的比价模型,把“跨平台 vs 原生”的争论放到自己的项目场景里对比。
这和电商建站里“wordpress 和 shopify 的区别”其实非常像:WordPress 灵活可控、插件生态无敌,但你要懂自托管、性能和安全也要自己操心;Shopify 是托管式电商,开箱即用,但也受平台规则约束。选哪个?取决于你有多少技术能力、需要多快上线、业务复杂度上限在哪里。移动端技术选型同理:RN 或 Flutter 好比托管式平台,快速上线、一套代码双端覆盖,代价是你在性能与底层控制上让渡一部分话语权;原生好比自建站,前期投入高,但后期上限大、掌控力强。
5.2 一张可以直接抄走的决策清单
我根据自己的项目经验整理了一张清单,遇到“要不要用 RN/Flutter”的纠结时,可以逐条打分:
- 业务复杂度:应用是否只是表单、列表、数据展示和基本交互?如果是,跨平台完全够;如果涉及复杂动画、音视频编辑、AR、高性能绘图,原生更合适。
- 性能敏感度:用户的核心使用路径上,是否存在对首屏耗时、滚动流畅度、动画跟手度要求极高的场景?如果存在,原生更稳妥。
- 团队构成:团队主要由前端 React/Vue 工程师构成,短期内没有足够预算组建两套原生团队?那么 RN 仍然是高效选项。
- 系统 API 依赖:是否深度使用相机、传感器、NFC、安全芯片等系统能力?跨平台方案虽然能封装,但深度和实时性通常弱于原生。
- 产品生命周期:是快速验证一个 MVP,还是要做一款五年十年的旗舰产品?MVP 阶段跨平台更香,长期旗舰产品原生的架构延展性更好。
- 运维和招聘:你能否长期负担跨平台框架的版本升级和第三方库维护成本?团队所在地能否稳定招到原生工程师或 RN 工程师?
这套清单每次用都能帮你把情绪化的争论拉回到具体数据上:没有标准答案,只有最符合你当前约束的答案。
5.3 对 RN 新手和正在纠结团队的一点建议
最后给正在学 RN 的朋友一点实在的看法:RN 绝对没有白学。它的核心是 React 心智模型,这套模型在前端、全栈、甚至桌面端开发里都是通用的;就算 RN 本身有一天被某种新技术完全替代,你对组件化、状态管理、声明式 UI 的理解依然值钱。而且 RN 的开源生态、社区规模、企业采用量仍然庞大,市场上依然有很多 RN 岗位在招人。真正值得你警惕的不是 RN,而是“迷信任何技术栈具有普适性”的思维。
我自己在实际项目里也走过类似的弯路:一个工具型 C 端应用,最初我用 RN 来做,两个星期上线 MVP,效率确实高;但后来业务重心转向高动态交互的创作工具,RN 越来越吃力,最后才决定重写成原生。如果当初一开始就上原生,可能前三个月都在搭架子。回过头来看,快不一定是缺点,但技术栈天花板配不配得上业务的野心,一定要提早想清楚。这也是 Shopify 这个案例给我最大的提醒。