
这两天移动开发圈子里有一条消息传得挺快Shopify 官宣了新的 iOS 架构默认采用 SwiftUI同时逐步把 React Native以下简称 RN从主应用的核心 UI 里替换掉。乍看标题确实够“倒反天罡”——一家在 2019 年高调宣布“All in React Native”、砸了 6 年时间、写了几百个原生桥接模块的电商巨头最后居然转头又回到原生开发。很多人第一反应是RN 是不是不行了这篇文章不打算复述新闻而是想借 Shopify 这个案例把 RN 在大型复杂业务 App 里的真实边界讲清楚。我会从当初为什么押注 RN、后来为什么扛不住、以及普通团队能从里面拿走什么三层来拆。无论你正在用 RN、在选型还是已经遇到“启动白屏”“长列表卡顿”这类头疼问题这篇都值得花 10 分钟看完。1. 事件脉络还原6年投入到底发生了什么1.1 从 All in 到集体回退的三个关键节点回顾 Shopify 和 RN 的这段关系其实有三个节点非常值得注意。第一个节点是 2019 年。Shopify 正式宣布把 iOS 主应用重写为 React Native当时的理由是“电商业务变化太快促销玩法、营销组件、店铺装修这些功能需求太多原生开发两条端线并行根本排不过来”。那时候 Shopify 手上有大量 Web 背景的工程师RN 让这批人用 JS/TS 写移动端等于直接把一个很庞大的 Web 开发池子拉进了移动端战场。这个决定在当时看逻辑完全自洽。第二个节点是 2022 年。Shopify 官方博客发布了一篇相当有分量的文章宣布主应用里大约 99% 的代码已经跑在 React Native 上同时和原生端之间搭了 300 多个桥接模块。这组数据一出来业内一度把它当成 RN 的大型成功案例——你看连全球头部的电商 SaaS 平台都能做到这种深度RN 的工程能力应该没问题了吧第三个节点就是 2024 年底到 2025 年初的这次转向。Shopify 在官方博客里明确表示新的 iOS 架构默认采用 SwiftUI并且逐步用原生 UI 替代掉 RN 渲染的界面。注意这里说的是“新架构默认 SwiftUI”而不是“立刻删光所有 RN 代码”。它更像是一次战略重心的转移核心体验回归原生RN 退到那些能接受异步加载、对首屏要求不那么苛刻的局部场景。1.2 别急着喊“RN 已死”这次回退的准确边界很多文章一看到“Shopify 放弃 React Native”就开始唱衰这种情绪化判断对技术人有误导。实际上 Shopify 的回退不是“删除”而是“换优先级”。从官方表述和工程实践来看它保留了 RN 在部分场景的使用尤其是商户端的一些嵌入组件、低频配置页面、营销活动页。这些场景的特点是可以接受加载延迟、交互层级浅、不需要和 iOS 系统能力做太深的集成。而主应用里用户每天要打开几十次的商品详情、购物车、结算流程、个人中心这些路径已经开始逐步原生化了。换句话说Shopify 真正否定的不是 RN 这个技术而是“RN 作为整个 App 的地基”这个架构选择。这和“RN 不行”是两码事。理解了这个边界后面所有讨论才有意义RN 不是不能写业务而是看它被放在哪一层。2. 复盘 2019押注 RN 在当时根本不是昏招2.1 那个时间点RN 几乎是最合理的选择现在回头看 2019 年的技术环境我会直接说Shopify 当时选 RN 不但不傻反而是非常理性的决定。先看技术格局。2019 年 Flutter 还没有像后来那样形成大气候iOS 这边的 SwiftUI 刚刚发布不到一年生态不成熟安卓端的 Jetpack Compose 还根本不存在。RN 经过前几年的版本迭代虽然还有各种性能争议但至少在“一套代码跑双端”这个点上是当时唯一有大量线上案例、有 Facebook 在背后持续投入、社区生态相对完整的选择。你不选它可选的真不多。再看 Shopify 的团队结构。作为一家电商 SaaS 公司Shopify 的 Web 工程师数量远远大于原生移动端工程师。RN 的语法基于 JS/TSUI 写法接近 React一个能写 React 的工程师基本一两周就能上手写移动端页面。这意味着什么意味着 Shopify 不用为了维持两端原生开发去重新招一倍的人也不用让 iOS 和安卓团队各自做一遍效果经常不一致的界面。它用很低的组织迁移成本换来了巨大的开发产能。2.2 “一套代码两端复用”对电商公司的真实诱惑电商公司的业务节奏和一般工具类 App 完全不一样。今天要上一个秒杀页明天灰度一个推荐策略后天评论区改版——这些需求如果走原生双端从排期到开发到审核一个看似简单的活动页两周能上线就算快的了。RN 给了 Shopify 另一种可能性大部分页面逻辑用 JS 写两端共用发布节奏也灵活得多。尤其对于营销活动这种“生命周期短、形态变化快”的页面RN 的敏捷优势是原生很难匹敌的。从生意角度想这就像你开了一家店客流少的时候租个铺面什么都包比自己花大钱买地盖楼划算得多。技术选型也有类似的边际成本曲线问题只在于——当客流大到一定程度租铺面的账就开始不划算了。2.3 类比解释像“租铺面”和“买店面”的区别我们拿开店来打比方。早期业务规模不大团队小用 RN 相当于租铺面装修省事、开张快、前期资金压力小不用在平台上投入太多。但当你每天的客流量从几百人涨到几万人铺面的租金、水电、物业费、人员调度成本每一样都会水涨船高。更关键的是你发现客人的核心体验——进店速度、商品陈列的流畅感、结算效率——很多都受限于铺面本身的层高和格局你再怎么加柜子、改灯光都补不上结构性短板。这时候你自然会去算一笔账与其长期交租金不如自己买地盖楼。Shopify 这次回退原生本质上就是这么一笔账。问题是租铺面的人往往一直到交了大几年租金之后才真算明白这笔账。技术选型也一样很多成本不是写在第一年的采购单上而是藏在后面五年的每一次适配、调试和团队协作里。3. 压垮骆驼的关键问题RN 在大型电商 App 上的四个真实瓶颈3.1 启动白屏不是玄学是架构决定的先说网上搜“react native 启动白屏”出来最多的那个问题。RN 应用启动时系统要做的事比原生应用多得多初始化 JS 引擎、读取或下载 Bundle、解析 JS 代码、执行渲染逻辑然后才能把第一帧画面交给用户。多了这一步首屏自然就慢。在低端安卓机上这个体感差距尤其明显转圈几秒钟不是开玩笑。有人说新架构和 Hermes 引擎不是已经解决这个问题了吗确实改善了不少但改善不代表消除。对绝大多数业务团队来说这仍然是一个需要细心优化的点要合理预加载、要拆 Bundle、要做启动帧占位稍有不慎启动时长就上去了。但一个普通的原生 App 根本不需要面对这些问题系统提供的能力原生就能直接用。电商又是对首屏极其敏感的行业用户打开 App 三秒内没看到商品可能已经切到竞品去了。这个体验损耗对 Shopify 这种体量的平台来说是真金白银的损失。3.2 Bridge 翻译成本每个操作都多一道“中间商”RN 的 JS 层和原生层之间靠的是一个叫 Bridge 的桥接通道。每次 JS 要调用一个原生能力比如读取相册、获取定位、播放视频都得把数据序列化成一个消息跨线程传过去再等原生处理完传回来。我把这个理解为“中间商”本来两个人可以直接对话现在非要经过一个翻译虽然大部分时候翻译够快但每句话多 0.5 秒聊一小时天你就受不了了。具体到 App 里哪些场景最受伤高频交互的页面。比如商品列表快速滚动时JS 线程要不断接收原生传来的滚动事件、计算渲染内容、再通过 bridge 把 UI 指令发回去比如用户在输入框里打字每敲一个字母都触发 JS 逻辑和原生键盘的同步再比如地图拖拽、播放器手势、富文本编辑这些操作只要频率一高中间商成本就变得肉眼可见。RN 新架构里的 TurboModule 和 JSI 确实把通信方式改进了不少但问题在于一个像 Shopify 这样积累了 300 多个桥接模块的大型应用存量代码不可能一夜之间全部迁到新架构。你只能一边背着旧债一边小心翼翼地试新方案这种状态下性能优化寸步难行。3.3 长列表与复杂页面电商的“主战场”恰好是 RN 的弱项做电商的都知道商品流就是生命线。首页信息流、搜索列表、商品详情页、购物车、优惠券聚合页这些全是长列表和复杂嵌套页面的组合。RN 在这类场景下要做好不是做不到而是成本和收益完全不成正比。RN 的 FlatList 虽然基于虚拟化渲染但在内存占用和滚动帧率上和原生 UIKit 的 UITableView / UICollectionView 还是有可感知的差距。尤其当列表里有大量图片、视频、富文本样式混排时JS 线程的压力会急剧上升。商品详情页更离谱往往是几十个模块叠在一起每个模块都有自己的数据请求逻辑和埋点RN 写起来表面上很组件化但真正优化性能时你会发现需要深入到 Yoga 布局引擎和原生渲染链路里不是普通前端工程师能搞定的。SwiftUI 那边则完全是另一种体验。大量页面结构可以通过原生布局和系统控件直接实现滚动流畅度和内存表现天然优势明显而且能零成本调用 iOS 系统最新的能力。对 Shopify 这种“商品体验就是产品生命线”的公司来说长期让核心商品路径跑在性能常年吃紧的 RN 上无异于让主力球员穿着拖鞋上场。3.4 生态断裂每一次系统升级都是一次“全村补课”RN 的社区生态虽然庞大但在“系统级新特性跟进”上永远慢半拍。iOS 每年 6 月发布新系统RN 往往要等一段时间才能适配一些刚推出的原生框架和 APIRN 要么不支持要么需要等第三方封装。对普通小 App 来说晚几个月跟进没什么大不了但对 Shopify 这种必须第一时间兼容最新 iOS 版本、必须在每年系统更新后保证全功能可用的平台来说这个“等待窗口”就是纯成本。更折磨人的是 300 多个桥接模块的维护。每个模块都依赖 RN 版本、原生 SDK 版本、系统版本这三者的匹配。RN 从旧架构往新架构迁移的时候这些桥接模块几乎全要重新过一遍iOS 系统大版本更新的时候社区里的第三方 SDK 也未必能同步适配最后往往是团队花大量时间当“人肉胶水”去修补各种版本兼容问题。这些隐性成本项目早期根本看不出来日积月累才慢慢显现。4. 账本的另一面组织协作与人才成本往往比代码更深4.1 双栈团队的“交接棒”游戏纯看代码层面RN 的问题还能靠加缓存、拆包、性能优化补救但组织层面的沟通损耗是很多团队低估的大头。RN 项目意味着团队里同时存在“JS/RN 工程师”和“原生工程师”以及一个永远存在的灰色地带。一个功能出问题了JS 层觉得是原生的问题原生层觉得是 JS 的问题最后两边拉会排查半天发现是桥接层的数据格式不匹配。这种“交接棒式”的协作初期还能靠大家自觉规模大了以后每天都会消耗大量时间在跨层沟通上。我见过不少 RN 团队工程师一半精力写业务另一半精力在群里澄清问题边界。Shopify 作为重度 RN 用户双端加桥接模块的复杂度只高不低。当线上问题需要同时盯 RN 的 JS 堆栈、原生崩溃日志、桥接层数据日志的时候排查链路的长度和难度都是指数级上升。技术债务不只是代码债务组织协作的摩擦同样会变成产品迭代的刹车片。4.2 新架构迁移旧债还没还完新债又来了RN 新架构发布之后社区有一个说法新架构很美好但迁移很痛苦。这个痛苦在 Shopify 这种体量上被放大了无数倍。新架构意味着每一个旧的桥接模块都需要适配新的接口约定废除的 API 需要全部重写很多以前依赖的第三方库也需要等作者更新。更麻烦的是新架构和旧架构之间的兼容策略本身就需要精细设计线上存量用户不能直接一刀切升级。对团队来说最现实的问题不是“要不要升级”而是“人都在业务上谁有时间来做这件事”。不做技术债越垒越高做又挤占业务资源这几乎是所有大型 RN 团队的共同困境。4.3 人才池的变化与招聘的悖论还有一个经常被公开讨论却始终没解的问题RN 的人才池初级人多高级人少。很多前端工程师会写 RN但遇到底层性能瓶颈、原生交互冲突、内存泄漏这类问题就需要非常深的原生和引擎底子。市场上这样的人本来就稀缺还要同时理解电商业务的复杂逻辑就更难招了。而原生 iOS 开发的人才池虽然也在变化但至少在一线城市找几个能把 SwiftUI 和性能优化搞定的工程师比找一个“RN 深度优化专家”要靠谱得多。这个人才悖论带来的结果是RN 项目越到后期团队越容易被极少数核心骨干的能力所绑定。项目做得好往往靠的是几个能两头通吃的“超人”而不是框架本身。一旦这些超人离开团队的持续运维能力就会被打回原形。5. 案例的迁移你可以从 Shopify 的经验里拿走什么5.1 先用一张打分表判断你的 App 适不适合 RN我不打算劝任何人“一定别用 RN”因为 RN 在合适场景下确实能大幅提效。但如果你正在进行技术选型我建议你先拿一张打分表老老实实给自己的项目做个评估。判断维度适合 RN 的得分点1不适合 RN 的得分点-1首屏要求可接受 loading 页或启动几秒3 秒内必须出首帧商品/内容交互复杂度表单、列表、静态展示富文本、视频剪辑、手势绘制、高频动画iOS 占比iOS 用户占比低安卓为主iOS 用户占比高且重视苹果生态体验团队构成前端/Web 工程师多原生力量弱原生工程师充裕前端基础薄弱业务更新频率营销页、活动页高频改版核心交易流程稳定更重视稳定性团队规模小团队追求快速上线大团队需要长线维护和高性能边界如果总分偏正向用 RN 没什么问题如果偏负向尤其是首屏和交互复杂度这两项都亮红灯我建议你慎重。就算必须用也应该考虑“只把营销页”、“配置页”这类低风险场景拿去跑 RN而不是把整个 App 的底盘都交给它。5.2 已经在用 RN 的团队可以这样“软着陆”如果你已经在 RN 项目里投入了很多又不能立刻推翻重来也不用慌。Shopify 的案例说明回退原生不是一蹴而就而是一个渐进过程。你可以把这件事当成一次“架构减肥”分步走。第一步挑出“不能接受白屏”的核心路径。电商 App 里通常就是首页、商品详情、购物车、结算、订单列表把这几条路径明确列为“原生优先”。第二步用一层原生壳把核心路径包起来每做一次迭代就把其中一条路径从 RN 切换到原生。第三步把 RN 收敛到一个独立子模块只负责那些可以接受异步加载、有独立内容边界的页面比如活动页、帮助中心、店铺装修配置页。这种“软着陆”的好处是不会打断业务节奏也不需要再造一个完全平行的新 App团队能边做边趋近目标。我有一个比较深的体会真正的失败不是选错了技术而是选错之后却没有给自己留一条可以逐步调整的路。5.3 把“桥接层”和性能监控当成一等公民还有一个很多团队容易忽略的点如果你一定要用 RN请从一开始就把桥接层和性能监控当成一等公民来治理。桥接层不该只是封装一个原生能力然后懒得上文档而要有清晰的接口规范、超时处理、降级策略和日志追踪。性能监控也不该只在测试阶段看两眼要把启动时长、首帧时间、卡顿率、JS 线程占用、桥接调用耗时这些指标全部埋进线上监控。这样等哪一天业务量上来了你手里至少有一份数据能明确告诉自己瓶颈到底是在 JS 逻辑、桥接通信还是原生控件本身。实际上很多 RN 项目走到后期变得不可维护不是因为框架上限太低而是连基础的可观测性都没做到出了问题只能靠猜。等你意识到要补这些的时候往往已经积重难返。5.4 没有“永远正确的框架”只有“边界清晰的设计”聊到最后反而想说点更大面上的事。从我自己的开发经历来看平台磕磕绊绊踩过的坑太多了。早期我也曾迷信某种“统一技术栈梦”觉得一套代码能跑两端就是终极解法后来才慢慢明白技术选型更像是一种“边界设计”你必须在每个具体场景里把“哪里用 RN”、“哪里用原生”的分界线划清楚而不是让某一种技术统治全 App。RN 依然是一个有用的工具尤其适合中后台、工具类、低频展示型 App它的开发效率和跨端一致性依旧有吸引力。但如果你想做的是重体验、重性能、用户每天高频使用的大型应用至少在核心路径上原生依然是那道最稳的地板。6. 最后说点个人的体会我在实际开发里见过不少团队最初都是抱着“省人力、提效率”的心态进入 RN结果在性能优化、版本适配、跨层沟通上花掉的时间反而比重写一次原生还多。我不是说 RN 不行而是想说押注单一技术之前一定要先盘点一下自己的核心业务场景到底有多复杂、用户对体验的容忍度有多低。每次技术选型我都建议团队问自己一个问题如果这个方案真的半路搞不下去了我们有没有退路退路不一定是一条完整的原生副线但至少要在核心业务路径上保留原生实现的可能性或者一层足够薄的业务抽象让每个页面都能独立替换。留好逃生舱才能真正大胆地向前跑。最后再分享一个小技巧如果你现在也在用 RN 写重业务应用试着把一个最核心的长列表页面改成原生实现只改这一页然后连着用一周。看看卡顿次数、加载速度、用户反馈有没有变化。很多时候数据会替你做决定。