
1. 一篇公告引发的震动Shopify 官宣放弃 React Native 的完整时间线2024 年下半年Shopify 移动端工程团队在官方技术博客上发了一篇公告大意是iOS 端的 React Native 代码要逐步迁移回 SwiftUIAndroid 端逐步迁移到 Kotlin整个过程预计要两年左右。消息一出国内外开发者社区直接炸了锅。毕竟 Shopify 是从 2018 年就开始把核心 App 押在 React Native 上的期间输出了大量工程实践现在居然亲口说“RN 已经到极限了”。作为一个从 Flutter、React Native 到原生开发都摸过一遍的移动端从业者我第一反应不是“React Native 要凉”而是更想搞明白一件事这六年里Shopify 到底经历了什么才会宁可吞下两年代码重写的苦果也要调头更关键的是这个案例对每天都要做技术选型的我们有什么实际的参考价值其实这次公告也不是说“明天就把仓库里所有 RN 代码删掉”。原文的核心意思是过去很长一段时间新功能都默认用 RN 实现接下来这个默认选项会反过来——新功能优先用原生写存量 RN 代码逐步替换两年是预期的全量迁移窗口。用一句话概括这是一次有计划、分阶段、仍然会保留部分 RN 组件的“用脚投票式撤退”。1.1 从 2018 到 2024RN 在 Shopify 的六年浮沉先把时间线捋清楚后面分析原因才有依据。2018 年Shopify 正式全面拥抱 React Native。包括核心购物 App、商家管理 App 在内都陆续向 RN 迁移。那几年 Shopify 内部的默认原则非常激进“能用 RN 写的就不用原生”。产品、设计、测试、发布的整个协作流程都围绕“一套代码跑两端”重新组织。2019 到 2021 年是蜜月期。Shopify 对外输出了很多 RN 工程实践模块化架构、统一设计系统、端到端测试方案。他们的 App 迭代速度肉眼可见地变快大量 React 前端工程师经过少量培训就能直接往移动端提交代码业务方自然高兴。2022 到 2023 年风向开始变了。React Native 社区全力推进新架构Fabric、TurboModules、JSI对大项目来说这本身就是一次极其痛苦的迁移。与此同时Shopify 的 App 功能越堆越多复杂的商品配置、实时库存、买家聊天、图片瀑布流、AR 试穿这些重度场景在 RN 上的表现开始明显滑坡。2024 年公告正式落地。六年的 RN 纪元进入倒计时。1.2 公告里没说出口的三句潜台词下面这三句是我根据公开信息和行业经验提炼的公告原文里未必有原话但对理解整件事非常关键。第一性能问题绝对不是“最近才出现”而是“最近才严重到影响商业指标”。Shopify 这种量级的电商平台启动时间和卡顿率的波动会直接反映在转化率上。当技术债积累到能算成具体的真金白银损失时任何团队都不会再犹豫。第二人才结构出了大问题。能把 RN 用得好的工程师理论上必须同时懂 JavaScript、React、原生开发、移动端性能优化。这种“全栈移动工程师”全球都稀缺薪酬被哄抬得很高。与其花两倍价钱招复合型人才不如把团队拆成纯粹的 iOS 和 Android 两个方向人才池瞬间就大了好几倍。第三社区生态进入了代际切换的阵痛期。新架构是未来但存量项目升级的成本极其高昂。对 Shopify 这种规模的 App 来说停留在旧架构意味着逐渐被社区甩开升级到新架构又要脱一层皮。这种两难局面本质上就是促使他们重新评估技术栈的深层原因。2. 回到 2018 年Shopify 当年凭什么把宝押在 RN 上现在很多人喜欢用结果倒推说“Shopify 都撤了说明 2018 年选 RN 就是错的”。这是典型的幸存者偏差。判断一个技术选型对不对必须回到当时的约束条件里去看。Shopify 当年面临三个非常具体的矛盾。第一业务扩张速度远超移动端团队的建设速度。Shopify 的 App 不只是购物入口还承担着订单管理、库存管理、客户沟通、营销工具等商家后台功能是一个极其庞杂的移动工作台。如果全走原生iOS 和 Android 团队至少要同步扩张一倍才能跟上业务喊需求的节奏而 2018 年的原生工程师市场根本没有这么大的供给。第二Web 技术栈是 Shopify 的根基。这家公司本身就是 React 的重度用户后台、商家工具基本都跑在 JS 生态上。选 RN意味着几百名现成的 React 前端工程师能直接往移动端投入这是任何一家高速成长的公司都无法忽视的组织红利。第三电商业务对热更新有执念。大促期间的活动页、商品展示逻辑经常要临时调整RN 配合热更新方案能绕过应用商店审核直接推送 JS 更新。对电商来说少等一次审核可能就意味着多好几天的活动窗口。所以 2018 年的选择不是头脑发热而是一笔理性的账在工程师资源不足、业务需求高速增长的约束下用一套 JS 技术栈覆盖两端是能把产品最快做出来的路径。2.1 一套代码池带来的组织红利大多数人在讨论 RN 时只聊技术忽略了组织层面的巨大价值。对 Shopify 来说RN 最大的收益其实是“工程师资源的弹性”。举一个很直观的例子当营销活动需要临时加三个商品展示组件时原生团队可能要排两周开发档期RN 团队只需要从 Web 项目抽调两个前端工程师配合后端一周内就能交付并灰度上线。这种资源调度的灵活性在 2018 年那个时间点上的价值怎么强调都不为过。2.2 早期性能差距“不明显”的假象另一个容易被忽略的事实是RN 在 App 功能简单、页面结构浅的时候启动速度和流畅度与原生相比差距并没有想象中大。Shopify 最初几个版本功能克制JS 引擎即使在偏低端的安卓机上也能扛住。这产生了一个很危险的错觉团队以为“RN 体验已经接近原生”。直到功能开始堆叠图片列表变多、页面层级变深JavaScript 线程的性能瓶颈才逐步暴露。最坑人的是性能是渐变恶化的不是一夜崩盘团队在相当长一段时间里都处于“好像有点卡但还能忍”的状态。等量变引发质变已经是几年之后了。3. 真正压垮骆驼的三根稻草性能、抽象泄漏、团队结构把“RN 不够好”这种模糊感知拆开来看Shopify 遭遇的问题主要落在三个维度性能表现、抽象层的完整性、团队结构的合理性。这三个问题单拎出来都不致命但叠在一起就是一个无解的局。3.1 电商级负载下的性能天花板先说最直观的性能问题。React Native 的架构决定了 JavaScript 跑在独立的 JS 线程里UI 布局和原生控件的交互要通过 Bridge或下一代 JSI通信。每一次手势、每一次状态变更、每一次页面跳转都有跨语言调用开销。电商 App 是典型的高负载场景一个商品详情页就是十几张大图、动态推荐流、实时库存、买家评论瀑布流。RN 对长列表的优化一直在进步但在这种负载下中低端安卓机上掉帧、滚动卡顿、内存上涨几乎是必然的。举一个特别常见的例子。很多开发者在处理长列表时第一反应是调 FlatList 的 propsFlatList data{products} keyExtractor{(item) item.id} renderItem{renderProductCard} getItemLayout{(data, index) ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index, })} windowSize{5} maxToRenderPerBatch{10} initialNumToRender{8} /这些参数确实能控制渲染窗口但电商列表的单条 item 本身就非常重——十几张图、异步库存、曝光埋点当渲染成本高到一定程度窗口调小只是把卡顿从“滚动中”挪到“滚动前”。真正的解法是把列表 item 下沉成原生组件或者干脆把核心页面迁回原生。Shopify 在实践中反复撞的正是这类墙。还有一个绕不开的痛启动白屏。App 启动时要先初始化 JS 引擎、加载 JS Bundle、执行首屏渲染在复杂 App 里这一步可能长达数秒用户看到的就是白屏或冻结的闪屏。原生开发里启动链路可以精确把控到每一帧在 RN 里能做的优化手段却极其有限。3.2 抽象泄漏写一次跑两端怎么变成维护三套代码React Native 最动人的承诺是用 JavaScript 写业务底层自动渲染成原生 UI所以体验能接近原生。但真实工程里这个抽象到处在漏。当你需要做渐变导航栏、自定义手势、共享元素转场动画或者深度集成 AR、NFC、后台定位这类系统能力时RN 的组件和 API 往往不够用你必须自己写 Native Module把 Swift 或 Kotlin 代码通过 Bridge 暴露给 JS 调用。于是出现一个很荒诞的局面项目名义上是“一套代码跑两端”实际上要维护四块东西——JS 业务层、iOS 原生模块、Android 原生模块、连接它们的 Bridge 通信层。出问题时排查链路横跨三个运行时谁都不知道 bug 到底出在哪一层。软件工程里有个著名的“抽象泄漏定律”任何抽象都无法完全隐藏底层复杂性它只会换个地方冒出来。RN 把这个定律演绎得淋漓尽致。我身边就有一个鲜活的例子。一个朋友的团队用 RN 做 App接了一个只有原生 SDK 的定制地图组件没办法只好自己写了两个 Native Module 分别封装 iOS 和 Android 的 API。结果地图 SDK 升了一次级两个模块都要跟着改改完还要重新打包、提交审核。算下来这个“跨端方案”不但没有省事反而比纯原生多维护了一层胶水代码。3.3 团队和生态带来的隐性成本性能问题还能用工程手段硬扛团队和生态的隐性成本更折磨人。先说人才。市场上自称“React Native 工程师”的人很多其实只是在 Web 端写过 React对 iOS 和 Android 的原生机制了解有限。让这样的工程师写出来的 RN 页面一旦碰到复杂的原生交互根本兜不住底层问题。更可怕的是网上流传的大多数 React Native 教程只会教你怎么写待办事项和计数器真实生产环境的复杂度——几十个模块的依赖、多层路由的跳转、端到端的性能监控——教程里一个字都不会提导致大量团队对 RN 的上手难度产生了严重误判。真正的全栈移动工程师不仅稀缺价格还贵。对 Shopify 来说与其持续为这种稀缺人才支付溢价不如把团队拆成两个原生方向用市场供给更充足的原生工程师来补位。再说生态。RN 社区的迭代速度极快主版本和 Breaking Change 几乎年年都有。2023 到 2024 年社区全面转向新架构Fabric、TurboModules、JSI每一样都是一轮迁移工程。对小型 Demo 来说这可能只是改几行配置对 Shopify 几十个模块、几十个页面组件的大型 App 来说这就是持续数月的系统性项目。更麻烦的是这种迁移以后每隔一两年就要来一次。与其被社区牵着走不如退回到一个稳定的技术底座。4. 两年重写的经济账这笔迁移到底亏不亏外界看到的是“巨头要重写代码”行业里看到的是“天量迁移正在发生”。那这笔账到底怎么算Shopify 才觉得划算4.1 显性成本与潜在收益的对照先看成本。成本项目具体内容代码重写存量 RN 页面全部用 SwiftUI 和 Kotlin 重写双轨并行RN 与原生代码共存两套工具链和监控体系同时维护团队重构RN 工程师转学原生技术栈培训和磨合吃掉生产力机会成本新增功能的开发速度在迁移窗口内明显下降这四项加在一起粗算就是一笔每年投入巨大的长期工程而且还要承担迁移期间新功能上线速度变慢的市场风险。但为什么 Shopify 还是选择做因为收益同样可观。收益维度具体内容性能可控启动时间、滚动流畅度、内存占用回归原生水平人才池扩大原生工程师供给充足招聘难度和成本下降降低外部依赖不再被 RN 社区版本迭代与新架构迁移不断裹挟长期维护原生技术栈成熟稳定隐性维护成本持续走低用两张表放在一起看就清楚了RN 让 Shopify 在前几年省掉了大量开发资源但也把一笔巨大的维护债推迟到了今天。现在一次性还清换来的是未来每一年技术底座的确定性。4.2 为什么这步棋只有 Shopify 这种体量的公司走得动但我必须强调账算得再漂亮也不是每个团队都复刻得了。Shopify 能承受两年代码重写前提是它的业务已经稳定增长不需要靠疯狂堆功能去抢市场。如果你所在的产品还在验证商业模式功能上线速度就是生命线那“两年重写”对你来说不是优化而是主动把脖子伸给对手。等你的原生版本终于写完市场和竞品可能早就换了一轮。技术选型没有绝对的对错只有适不适合当前的阶段。这句话不是安慰是做这个行业必须有的清醒。5. 看完大厂的选择普通团队应该怎么办聊完 Shopify 的故事最终要落到我们自己头上。结合我自己做过的 RN 和原生项目我给出下面这份不那么像风口的决策清单。5.1 选型前先问自己四个问题第一个问题团队里有没有能独立写原生 Module 的人注意是“能写”不是“能读”。如果没有RN 项目一旦遇到抽象泄漏你就会完全陷入被动只能求着社区和外包帮忙。第二个问题App 对性能的敏感度有多高内部 OA、后台管理、数据录入这类工具型应用性能要求低RN 绰绰有余内容消费、直播、编辑器、复杂交互动效这类产品RN 的短板会非常扎眼。第三个问题产品打算活多久只是快速验证一个想法RN 是好工具如果判断产品要做三五年以上且会持续变复杂原生开发在长期积累上的优势会逐渐显现。第四个问题团队的核心技术栈是什么全员 JavaScript 且不打算扩原生团队RN 几乎是唯一合理选项如果公司本来就有 iOS 和 Android 团队新增一层 RN 反而会造成职责模糊和重复建设。我用一个表给你做个快速对照评估维度更适合 RN 的场景更适合原生的场景团队构成以 JS/Web 工程师为主已有 iOS Android 双团队产品阶段MVP / 快速验证 / 内部工具长线复杂业务 / 高用户量级性能要求中低CRUD 为主高重度交互 / 媒体 / 动画生命周期1-2 年内的轻量应用稳定迭代 3 年以上的产品业务特性需要快速覆盖双端对启动速度和卡顿率有硬性指标5.2 真要用 RN这几条工程纪律能救你不是说 RN 完全不能用而是要用得像对待一件“有刺的珍宝”。第一条团队里一定要有原生技术负责人。哪怕他平时不写业务代码也要负责所有 Native Module 的技术评审和性能风险评估。前期看是养了一个“闲人”项目后期他会无数次从坑里把你捞出来。第二条从第一天就建立性能监控。启动耗时、白屏时长、帧率、内存占用这些指标不要等用户投诉了才去优化。RN 最大的悲剧就是问题积累到不可收拾才处理你完全可以在早期就避开。第三条克制对第三方 RN 组件的依赖。很多第三方库的维护者就三两个人一两年不更新是常态。核心业务组件能自己写就自己写非要用第三方库提前评估它的原生依赖质量和社区活跃度。5.3 出现这三个信号就该考虑换赛道了最后聊聊什么时候应该像 Shopify 一样转向。第一个信号你的 App 里原生模块代码量开始超过 JS 业务代码。这意味着你已经不是“用 JS 写原生”而是在“为了给 JS 打补丁不得不写原生”。当抽象层不再帮你抹平差异、反而在制造新成本时这个抽象已经失效了。第二个信号团队里最资深的前端开始频繁抱怨“这个交互用 RN 做不出来”或“这个性能瓶颈只能靠原生解决”。当最强的人反复触碰技术边界你就该认真评估是不是该换底座了。第三个信号每次 RN 大版本升级都会让团队陷入漫长的回归测试和兼容性修复。如果升级本身已经成为主要负担主动换赛道可能反而是成本更低的选项。这三个信号没有任何一个是在某个时间点突然出现的全是渐变。就像 Shopify 一样真正的决策从来不是一个晚上的灵光乍现而是在无数次性能评审、兼容性修复和招聘面试中一点点砸出来的。我个人这几年的体会是跨端框架本质上是一种“把快乐留给开发、把成本留给后期”的延迟策略。选技术栈本质上是在选“现在付钱”还是“以后付钱”。没有哪个选择永远正确它只是在某个时间点上基于当时的约束条件做出的最优博弈。所以别因为大厂撤退就觉得某种技术不行了也别因为大厂押注就无脑跟随。看清楚自己的阶段和约束比追随任何风口都重要。最后再分享一个细节公告发布之后有位 Shopify 工程师在社交平台上说过一句话大意是“我们并没有恨 React Native它陪我们跑过了一段非常重要的路只是现在这条路该分岔了”。我觉得这个态度特别健康。技术选型不需要忠诚需要的是在每个阶段做出对业务最有利的判断。愿你选型的时候想的不是“别人都在用什么”而是“我的团队和产品现在最缺什么”。