1. 一场六年的押注,为什么 Shopify 选择“回头”?
这两天移动开发者圈子里最热闹的话题,莫过于 Shopify 宣布把移动应用从 React Native 转向原生开发。放到别的公司身上,这可能只是技术团队的一次内部调整,但 Shopify 不是小角色——它的商家端 App 是全球数百万商户每天都在用的核心工具,日常处理的是商品管理、订单处理、数据分析、库存同步这类高频高负载业务。这样一个巨头押注 React Native 整整六年,然后掉头回到 Swift 和 Kotlin,消息一出,很多团队的技术负责人都在群里问同一个问题:那我们手上的跨平台方案,还要不要继续?
先说清楚,这不是一次突如其来的反悔。早在 2018 年前后,Shopify 就明确表示要把移动端押在 React Native 上,理由也很直白:双端复用一套业务代码,能大幅压缩开发周期,还能让 Web 前端的同学快速顶上移动端。当时这个决定在业内被看作 React Native 路线的重要背书,毕竟 Shopify 的工程体量摆在那,它愿意长期投入,说明这套框架在复杂业务下是能扛住的。六年里,Shopify 也确实对外分享过不少 React Native 大型应用的实践文章,包括性能优化、架构改造、模块化拆分,听起来一切都在正轨上。
结果呢?2025 年,他们公开宣布新应用将改用 Swift 和 Kotlin 编写,后续功能会逐步迁移到原生技术栈。
这个转折之所以让圈内震动,在于它直接撕开了跨平台方案最敏感的一个问题:当业务复杂度上升到某个量级,跨平台带来的开发效率红利,还能不能覆盖性能、稳定性和长期维护的成本?如果你所在团队正在做技术选型决策,或者在犹豫要不要踩进 React Native 这条船,那这次事件里透露出来的信息量就非常值得研究。下面我会把 Shopify 这次“回头”背后的技术逻辑、真实的性能瓶颈、跨平台与原生之间的权衡标准,以及它对整个移动开发生态的影响,一条一条拆开讲清楚。
2. 六年时间,Shopify 到底在 React Native 上经历了什么
2.1 当年入场时的逻辑:效率和团队复用优先
2019 年左右,先去回头看看 Shopify 当年做这个决定的背景。电商商家端应用有一个显著特点:业务迭代极其频繁,促销工具、物流规则、店铺装修、数据报表,几乎每个季度都有新功能上线。如果用原生技术栈做,iOS 和 Android 两套团队并行开发,光是一个需求从评审到双端联调上线,平均就要多出 40% 到 60% 的时间成本。而 Shopify 早期并不是一个移动端基因很强的公司,它核心是 Web 电商平台,技术团队里有大量 React 背景的工程师。选 React Native,本质上是用一套已经成熟的 React 生态去覆盖移动端需求,让前端团队能够直接参与 App 开发,招人也更容易——毕竟会 React 的人远比会 Swift 和 Kotlin 双修的工程师多。
所以当年这个决策从“组织效率”角度看,很理性。裁员不是拍脑袋,是用 Web 能力补移动端的短板,同时持续给 React Native 社区做贡献,试图让框架本身也跟上业务需求。六年里他们的移动 App 确实覆盖了绝大多数商家管理场景,很多小型商户甚至只靠手机 App 就完成日常运营,客观说 React Native 在中间扮演了重要角色。
2.2 撤退信号:性能与体验终究没跑赢原生
但问题也就出在规模和体验上。六年时间,Shopify 商家端 App 的功能模块越加越多,页面层级越做越深,React Native 的短板开始被成倍放大。先看一组非常直白的对比:商家打开 App 的第一诉求是快速查看订单或者修改库存,这种操作路径要求 App 启动要快、页面跳转要跟手、列表滚动要顺滑。React Native 在这几个维度上,和原生实现之间始终存在肉眼可感知的差距,尤其是在中低端 Android 设备上,JS 引擎初始化、Bridge 通信、视图树同步的开销会让冷启动时间明显拉长,快速滚动时还会出现掉帧。
对普通用户来说,从 1.2 秒优化到 0.8 秒可能感觉不明显,但对一个每天打开几十次的商家用户来说,这个差距就会积累成“这 App 卡卡的”的认知。而在应用商店的评分体系里,一次糟糕体验就可能换来一个一星差评。另外,电商类 App 对图片加载、列表性能、复杂表单交互的要求本身就比内容类 App 高出一截,React Native 在这些高频路径上需要开发团队做大量底层优化才能追平原生体验——而就算是追平了,也要持续投入人力去维护那些定制化的原生模块。
2.3 组织层面的隐性成本:双栈维护并不省力
还有一个经常被忽略的点:技术选型省下来的成本,往往会在组织协作里加倍还回去。表面上看 React Native 是“写一套代码跑双端”,但实际落到大型项目里,纯 JS 层很难覆盖所有能力,必须要写原生 Module 来桥接底层功能,比如相机扫码、推送、蓝牙打印、文件系统访问。一旦牵扯到原生代码,团队就分裂成 JS 业务开发、iOS 原生开发、Android 原生开发三条线,而这三条线之间是通过桥接层通信的,排查问题的时候经常要跨堆栈追踪:业务逻辑在 JS 层,异常却出在原生模块,中间还有异步桥接的丢消息问题。
Shopify 这种体量的团队,养 JS 工程师、iOS 工程师、Android 工程师的成本已经全部付出去了,既然如此,继续背着 React Native 这层额外复杂度就显得不划算。一位参与过大型 RN 项目的朋友跟我聊过:当你的团队已经同时拥有双端原生工程师的时候,RN 带来的“节省”就只剩心理安慰了,因为沟通成本和维护成本并没怎么降。Shopify 走到这一步,本质上就是算清了这笔账。
3. 为什么启动白屏、滚动掉帧这类问题总是解决不干净
3.1 React Native 的渲染管线,天生就比原生多好几跳
很多刚开始接触 React Native 的开发者,容易有一个错觉:界面上看到的组件最终就是原生组件,那性能应该和原生差不多。这个想法只对了一半。React Native 的渲染路径是这样的:JS 层负责生成虚拟 DOM,通过 Bridge(新架构里是 TurboModule 和 Fabric)把指令传给原生层,原生层再根据指令创建或更新真实的 UIView / Compose 视图。也就是说,你的 UI 代码跑在 JavaScript 引擎里,视图操作全部都要跨过 JS 与原生之间的那道边界,而这个边界的通信效率就决定了性能上限。
原生开发里,点击一个按钮直接执行 Objective-C / Swift / Kotlin 代码更新视图,中间没有额外跳转;React Native 里,点击事件要封装成消息传到 JS 层,JS 处理后再把更新指令传回原生层,来来回回多走了几趟。用户感知最明显的,就是列表快速滑动时的掉帧——滚动事件在原生主线程执行,而 JS 线程要同时处理业务逻辑和发送视图更新指令,一旦 JS 线程卡顿,列表就只能等它跟上,表现出来的就是滚动不跟手。这也是为什么“大型列表在 RN 里优化起来比原生费劲得多”。
3.2 冷启动白屏,本质是“JS 还没跑起来”
“react native 启动白屏”能成为高频搜索词,说明这不是小众问题。你可以想象一下 App 冷启动的完整时间线:系统先启动原生壳工程,接着初始化 JavaScript 引擎,等待 JS Bundle 从本地或者网络加载完成,然后执行业务代码,最后才渲染出第一帧界面。在这个链条里,任何一环耗时都会延续首屏白屏时间,而其中最不可控的,是 JS Bundle 的加载和解析。Shopify 这种大型应用,JS Bundle 打包出来动辄十几 MB 甚至更高,即便放在本地加载,解压、解析、执行的耗时都不是一个小数目。
为了优化这个环节,社区里常用的方案有这几类:拆 Bundle(按功能模块拆成多个 JS Bundle,按需加载)、代码瘦身(去除多余依赖以降低解析量)、开启 Hermes 引擎(Facebook 专门为 RN 打造的 JS 引擎,预编译字节码能显著缩短启动时间)、延迟初始化非首屏业务模块。这些手段确实能把白屏时间压缩,但每加一层优化,就多一分复杂度,而且始终有一个绕不开的事实:原生启动不需要等一个独立的 JavaScript 引擎先跑起来。这也是为什么很多团队做了一圈性能优化之后,最后还是回到“关键页面用原生实现”这条路。
3.3 大厂为什么扛不住:生态再好,也补不了系统级差异
有一点要公平地说,React Native 的生态这些年进步非常大,新架构(Fabric + TurboModule)也把通信性能和渲染稳定性提了一个台阶,社区里优秀的三方库也不断涌现。但生态弥补不了的是:底层操作系统、设备碎片化、系统级能力和交互范式之间的差异。iOS 有 iOS 的手势、动效、导航栏规范,Android 有 Android 的 Material Design 和返回手势,React Native 只能用“抽象层”去抹平这些差异,而抽象层一旦做得太厚,就会牺牲部分性能和原生体验。
我刚看 AirBnb 在 2018 年宣布放弃 React Native 时,技术博客里写过一句话:跨平台框架适合“把业务快速铺到两个平台”,但不适合“在两个平台都做到极致”。Shopify 这次选择本质上是在重复这个判断,只是时间点更晚,投入也更深。而这次“倒反天罡”的行为给了整个行业一个新的样本:一个投入了六年、拥有一流工程能力的公司,最后仍然觉得原生体验和组织成本更划算,那就不仅仅是“优化不到位”的问题了。
3.4 性能对比:一张表看清原生的不可替代性
| 关键指标 | 原生开发 | React Native | 差异说明 |
|---|---|---|---|
| 冷启动耗时 | 最低 | 额外增加 JS 引擎初始化 | 白屏问题更明显 |
| 列表滚动帧率 | 稳定 60FPS | 大列表容易掉帧 | JS 线程处理开销 |
| 复杂交互动效 | 可全线程掌控 | 依赖桥接,延迟更高 | 转场、手势难做细 |
| 内存占用 | 相对可控 | JS 运行时额外开销 | 中低端设备影响大 |
| 新系统特性适配 | 当天跟进 | 等待框架跟进 | 平台能力滞后 |
| 双端代码复用 | 低 | 高 | 效率与体验的取舍 |
这张表并不是说 React Native 一无是处,而是提醒你:如果你的业务核心是大量输入、复杂交互、高频刷新、动画定制,那原生方案的性能优势会体现在每一个用户操作细节里。相反,如果你的产品是工具型、内容型、管理后台型,对极致流畅度要求没那么苛刻,那么跨平台方案的效率红利依然实打实。
4. 从“RN 还是原生”到“WordPress 还是 Shopify”式的问题
4.1 技术选型为什么和企业建站很像
有一回我给一个做电商 SaaS 的朋友解释跨平台方案选择时,发现一个特别贴切的类比,就是很多人搜过的“WordPress 和 Shopify 的区别”。你是自己搞一套 WordPress 站点,用开源技术栈全自由度定制,换来的是掌控力,代价是服务器、插件安全、性能优化、迭代维护样样要自己扛;还是直接用 Shopify 这种托管平台,快速上线、无需操心底层,但定制能力天然被平台限制。
原生开发就像自建 WordPress:掌控力强,每个像素都可以按你想要的方式实现,但要自己养 iOS / Android 两套团队,成本高、周期长;跨平台开发就像用 Shopify:业务代码一套复用、上线快、开发成本低,但要接受框架层面的限制,底层出问题只能等框架更新。很多团队在做选型的时候,只顾着算“开发成本”,忘了问一个问题:你是想掌控体验,还是只想快速交付?这两个目标没有绝对对错,但它们指向的技术路线完全不同。
4.2 一个科学的跨平台/原生决策框架
根据我自己踩坑和看别人踩坑的经验,团队在做移动端技术选型时,可以从下面五个维度来做判断,每个维度给权重打分,最后综合决策:
- 业务复杂度:业务逻辑越接近 CRUD、列表、表单,跨平台越划算;业务越依赖复杂动画、底层硬件、系统深度集成,原生越靠谱。
- 性能敏感度:你的用户会天天用吗?每多一次卡顿都会影响留存吗?如果是,别选跨平台;如果是低频工具,跨平台的体验差距可以被接受。
- 团队基因:现有团队是前端强还是原生强?如果前端强但业务要快速覆盖双端,React Native 几乎是最佳选择;如果双端原生团队都已经齐备,不要为了统一技术栈而强行换框架。
- 迭代频率:产品处于验证期还是成熟期?早期快速验证选跨平台,用效率换生存;成熟期打磨体验,逐步替换到原生是不错的路线。
- 组织成本:跨平台框架不是免费的,它省的是“写 UI”的功夫,但会加“底层桥接、性能排查、框架跟进”的支出,团队越大这笔支出越明显。
4.3 你现在该不该跟着“跑路”?分场景给出答案
如果看完上面这些分析,你有点惊慌,想着是不是要把项目里的 React Native 全部推翻重写,先冷静一下。这件事要不要跟进,取决于你现在处于哪个阶段:
- 如果你正在做一个全新的 App,团队是前端背景,需要在三个月内同时跑通 iOS 和 Android——我仍然建议你用 React Native 起步,因为这时候生存比体验更重要。但你得从一开始就把性能预算这回事放在心上,提前设计好页面拆分、启动加载路径、长列表优化方案,不要等项目大了再回头补。
- 如果你已经有一个跑了两年的 React Native 项目,功能稳定,用户增长健康——别急着推翻。先把性能指标量化出来,统计冷启动时间、页面帧率、崩溃率,看看用户真实反馈里是否有体验类差评。如果一切在可接受范围内,继续维护完全可行。
- 如果你的业务已经做到头部,团队里有大量双端原生工程师,而你在用户反馈里频繁看到“卡顿”“闪退”“加载慢”这类关键词——那这时候确实可以考虑渐进式迁移。参考 Shopify 的做法,不是一次重写,而是从登录、首页、商品详情这些用户最常走的路径开始,用原生逐步替换,最终让跨平台层退居次要位置。
这里最关键的一点是:技术选型没有一劳永逸的解锁,所有方案都有它的生命周期,而你需要的只是在每个阶段做出当前最合适的选择。
5. 对开发者和技术生态的连锁影响
5.1 React Native 社区会因此“冷掉”吗
短期内一定会有影响,社区里难免出现“连 Shopify 都跑了,RN 是不是不行了”的声音。但我的判断是,React Native 不会被这次事件判死刑。原因也很简单:市场上大量中小团队对跨平台开发的需求真实存在,不是每个团队都需要做到顶级原生体验,也不是每个产品都值得维护两套原生代码。React Native 的设计目标一直是“够用且高效”,它确实不是万能的,但在适合它的领域里,它依然是最成熟、生态最好的跨平台方案之一。
真正受影响的是那些“什么都不管,先上个跨平台框架再说”的团队,Shopify 的案例等于给所有这种心态的人敲了一次警钟:如果你有长期的移动端投入规划,最终殊途同归,还是要回到对原生能力的深度掌控上。这也是为什么很多资深开发者反复强调原生基础的重要性,不是因为跨平台不值得学,而是因为最终的性能瓶颈一定发生在你没掌握的那一层。
5.2 对 Flutter、KMP 和其他跨平台方案的启示
Shopify 没有选 Flutter,而是直接回到原生,这件事对不同方案的影响也不一样。Flutter 的渲染引擎是自绘 UI,不走原生组件,性能和一致性比 React Native 更有保障,但它的语言是 Dart,和 Web 生态的复用率低,团队转型成本高;KMP(Kotlin Multiplatform)则是一种更“温和”的跨平台路线:共享业务逻辑,UI 层用原生实现,技术风险更小。对比下来你会发现,整个行业其实已经从“一套代码全包”的浪漫想象,回归到了“该共享的共享、该原生的原生”这种务实方式。这也是一个趋势:跨平台不再是万能银弹,而是工具箱里的一个常规选项。
5.3 对开发者个人:原生技能仍然是防身术
身在移动开发这个行业,技术选型的变化直接影响的就是我们的个人竞争力。React Native 会把前端工程师引入移动开发领域,这是好事,但它不能替代对 iOS / Android 系统机制的理解。很多人调试一个问题调了半天用 Workaround 绕过去,却根本不知道底层发生了什么——这种工程师在项目顺利的时候看不出问题,一旦碰上性能瓶颈、崩溃排查、系统特性适配,就会陷入被动。
Shopify 这个案例给所有移动开发者的提醒是:别把技术栈当成唯一的标签,真正值钱的是你理解问题的深度。无论你是写 Swift、Kotlin、Dart 还是 TypeScript,如果能拆到操作系统层面去理解渲染、线程、内存和网络,这类能力放到任何技术栈上都不过时。
6. 我的判断:这不是打脸,是技术理性的一次回归
外部看,Shopify 押注 React Native 六年后回到原生,很容易被解读成“当年选择是错的”。但我觉得,身处当时的情景,那个选择依然是一个合理的决定。2019 年的 Shopify,需要的不是全球最佳性能的 App,而是快速在一个庞大的 Web 用户群体里建立起移动端使用习惯。React Native 帮他们做到了这一点,如果没有 RN,他们的移动端覆盖速度很可能追不上业务增长需求。
到了 2025 年,业务已经足够成熟,用户量足够大,移动端足够重要,这时候体验的权重就会高过开发效率。用 Swift 和 Kotlin 重写核心路径,是一次对齐业务现状的理性调整。这个决策里真正值得学习的,不是“RN 不行”或者“原生最好”,而是他们一直很清楚自己要什么,且愿意为此做出代价高昂的决定。
对还在纠结技术选型的团队,我最后再说一句朴素的体会:框架永远在变,业务需求才是唯一不变的重心。选型的时候不要去追热点,不要看谁家大厂又用了什么,回到你自己的节奏里,找到那个能让团队在当下把业务跑得更快、更稳的组合。能随时承认上一个选择已经不适合现状,并且果断掉头,这种能力比任何单一技术栈都重要。