AI 没有杀死 React Native,它杀死了「省人力」这个理由 ai didnt kill react native ReactNative Expo Mobile AI AgentEngineering AI工程
4434 字
22 分钟

AI 没有杀死 React Native,它杀死了「省人力」这个理由

先说结论#

9 月 10 日,Shopify 官方博客发了一篇《Native is now the future of mobile at Shopify》,作者是 Head of Mobile Mustafa Ali。核心那句话写得很直白:

Coding agents changed what it costs to build mobile apps twice.

翻译过来:写代码的成本变了两次,所以 2020 年那个「全员 React Native」的决定也该重新算一遍。 他们决定回到 Swift + Kotlin,用 AI 重建全部移动 App。

社区的反应很热闹(Reddit 那个帖子 997 分 / 175 条评论,Theo 还做了个视频叫《Did AI Kill React Native?》)。但我的判断是:

AI 没有杀死 React Native。它杀死的是「因为养不起两套原生团队,所以只能选 RN」这个理由。

当实现成本被编码代理摊平,「省人力」从选型的主要矛盾降级成了次要项。剩下的变量里,有几条仍然对 RN 有利——尤其是一条几乎没人讨论的:OTA(热更新)。那是原生拿不到的能力,审核周期就是它的物理上限。

所以我们的决定和 Shopify 相反:cohub-mobile 继续用 React Native + Expo,做一个「原生质感」的客户端,并且自己写了 OTA 服务 yaota。

这篇不算谁对谁错,是两本账放在一起看:一本是 Shopify 的(几十个工程师、四个大 App、流程严谨);一本是我们的(小团队、两个平台、要快速迭代)。

一、Shopify 到底说了什么#

先说清楚他们的论证,因为这次官方口径比社区转述克制得多。

2020 年为什么选 RN: 不用写两遍功能、工程师能跨栈、少花时间追平台功能对齐。

2025 年 1 月他们的公开态度还是: RN 的未来是光明的,会继续投入。作者原话是「That was true based on what we knew then」。

2026 年为什么回头: 不是 RN 变差了,是「两个平台写两遍」的成本结构变了:

Native still means building and maintaining software on two platforms, that cost has not disappeared. What changed is that agents can now do enough of the implementation, translation, testing, and review work that it’s no longer the deciding factor it was in 2020.

代理现在能做掉足够多的实现、翻译、测试和评审,所以「写两遍」不再是决定性因素。

三个容易被忽略的细节#

1. 他们明确说了 RN 可以很快。

原文里有一句被大多数讨论忽略的话:

React Native apps can be fast. Ours are.

这句话很重要。把 Shopify 的决策解释成「RN 太慢」是不准确的。他们的理由是「为了每个平台的原生能力」,不是「RN 跑不动」。

2. 他们要做的下一笔投资,恰好是新架构迁移。

Shop app 那篇迁移复盘里写了一句关键的话:他们本来要为 Shop app 做下一笔大投入——适配 React Native 新架构(会涉及原生模块、渲染、共享边界)。在掏这笔钱之前,他们先做了个小实验:一个工程师花一周,用编码代理把这个 RN App 尽可能迁成 SwiftUI 版本。

实验结果够好,于是他们改成了重建。

所以「Shopify 拿旧架构时代的 RN 数据做对比」这个批评站不住。他们看的正是新架构要花的钱——然后决定不花了。

3. 他们没有一走了之。

对开源生态的处理方式我认为很体面:

  • React Native Skia:Shopify 继续赞助到 2026 年底,作者 William Candillon 会在之后 fork 并改名继续维护,原仓库归档。
  • FlashList(周下载约 200 万):承诺继续修关键兼容问题,同时正在和几家公司谈长期接管。
  • Restyle:维护到 2026 年底后归档,欢迎任何人 fork。

事后他们还给 Meta 的 RN 团队、William、Software Mansion(Reanimated)写了道谢。这个姿态比「我们用脚投票了」高明得多,也给生态留了缓冲期。

迁移本身的数据(Shop app)#

这篇数字我觉得比结论更有价值:

指标原生React Native变化
iOS 冷启动2466 ms3200 ms−23%
Android 冷启动2233 ms4433 ms−50%
Android 安装包184 MB293 MB−109 MB(−37.2%)
iOS 安装包68 MB67 MB+1 MB(+1.5%)
会话稳定性99.95%+99.5%+崩溃会话约 1/10

另外 Android 构建时间下降约 75%(iOS 基本持平),Pixel 上滑动 Feed 能到 120 FPS,而且「几乎还没做优化」。

注意这个结构的含义:收益主要落在 Android 上(包体 −109MB、启动 −50%、构建 −75%)。iOS 那边(+1MB、启动 −23%)是「差不多,略好」。这符合直觉——RN 时代 iOS 侧本来就有更好的底子,Android 侧一直是在追。

迁移方式也很具体:核心小组 6 个人搭原生地基和主路径,功能团队中途加入验证自己那块;同时刻意砍掉了一些页面、精简了另一些。前提是「对用户像一次普通更新」:保持登录状态、推送不断、埋点事件名和字段不能变。

真正值得学的部分:他们怎么用 AI#

这部分才是我看完最想记下来的,而且和框架选择无关。

Helix:一个不许「一次就对」的流水线。

他们试过直接让 LLM 看着 RN 代码库「一把梭」出原生实现——结论是不行,产出一大堆没法上线的代码。Helix 换个做法:

  • 开发者指一个屏幕,Helix 读 RN 代码,把它拆成一系列「几分钟能审完」的检查点
  • 每个检查点必须:用测试证明行为、和跑着的 App 做视觉比对、扛过两个对抗性代码审查者、拿到人类点头,才能 commit、才进入下一个
  • 每次评审的反馈会被记住,循环越跑越自动化

解决「代理没法快速自测」这个瓶颈。

他们描述的场景我们太熟悉了:

Agents can make code changes in seconds, but it takes them several minutes to test the output.

代理改代码是秒级,验证是分钟级;而验证靠无障碍树或截图,慢且脆。他们的解法是把业务逻辑彻底从 UI 里拆出来、能在桌面无头运行,再包一层 CLI 让代理直接查状态、导航、执行动作——迭代速度从分钟级变成毫秒级;真的需要模拟器时,再用远程模式驱动 UI。

Shop app 那次迁移里的两个工具。

  • 他们给 Pi 写了一个可复用的迁移工作流扩展——Pi 是我们做的编码代理,看到它出现在 Shopify 的官方博客里,我确实停顿了两秒。这个扩展里:专门的子代理去读 RN 源码、记录行为、出平台方案、实现功能、做一致性评审;任务说明要求人先确认,而且计划文件的接受状态绑定它的内容哈希——改了计划,之前的批准就作废。
  • 他们搭了个叫 Tardis 的调试工具,给代理结构化地访问跑着的原生 App 的事件、日志和状态,还能反向发命令;跨端一致性评审时,它能在命名检查点上同时抓 RN 和原生侧的截图与事件窗口,让代理比对事件名、次数、字段(时间戳、页面 UUID 这类天然不同的值被排除掉)。

但他们也说了实话:

Generated code could satisfy feature requirements while still introducing duplication, architectural drift, or performance problems.

生成代码能满足需求,同时引入重复、架构漂移和性能问题——所以 lint、测试、静态分析、性能检查、代码评审一个都不能少。原生专业能力仍然不可替代。

二、为什么我们做了相反的决定#

先交代背景。cohub-mobile 是我们自己的产品客户端(公开仓库),一个 Cohub 的原生 iOS / Android App。README 里有一句话我很喜欢:

This repository is the native iOS/Android client. There is no web target.

翻译成架构语言:用 RN 写,但按原生验收。 没有 web target,没有「先做 H5 再套壳」,界面全部是原生屏;唯一用 WebView 的地方,是用户发布出来的网页作品(那是内容本身,就该是网页)。

技术栈:Expo SDK 57 / RN 0.86 / 新架构 / expo-router / Reanimated 4 / gesture-handler / SQLite 缓存优先 / Logto PKCE。Expo 在这里是开源工具链,不是托管服务(我们不依赖 EAS)。

为什么同样的 AI 时代,我们算出相反的答案?因为我们那本账上有四个 Shopify 没有的条件。

1. 小团队 + 只有两个平台#

跨平台的收益公式是「两套变一套」。平台越多,这个收益越大;但只有 iOS + Android 时,它本来就只是 2:1。

Shopify 有几十上百个移动工程师、四个大 App、还要维护开源库。我们用 AI 写两套原生代码也不是不可能——但那意味着我们要同时维护 Swift 和 Kotlin 的验收、发布、性能基线,而我们连一个专职 iOS 工程师都没有。在他们的规模上,「写两遍」是工程组织问题;在我们的规模上,它是生存问题。

2. 我们用 Expo(这是被低估的关键变量)#

社区里有一句不太好听但很准的话:如果你开发 RN 却不用 Expo,你其实是在重造一个简陋版 Expo。

打包、签名、构建、原生兼容性、路由、原生模块生态——这些是 Expo 已经解掉的题。Shopify 没有走这条路,所以他们 RN 时代的很大一部分基础设施投入,本质是在替框架和工具链交学费。等这笔账和「写两遍」的账放在一起比的时候,RN 那边当然显得贵。

一个反证:我们连自建 OTA 都是严格贴着 Expo 协议做的(后面细说),从来没想过另起炉灶。

3. 我们把 OTA 当产品能力,而不是运维细节#

这是全文我最想强调的一点。原生开发拿不到 OTA——不是说没有工具,是审核周期决定了你不可能在发布后五分钟改变线上 App 的行为。

对我们这种小团队,OTA 是实打实的竞争力:

  • 线上出致命 bug,几分钟推修复,不用等几天审核,更不用祈祷用户去点「更新」
  • 节日运营要在当天换一个入口样式,OTA 可以按渠道、按比例放量
  • 灰度验证新交互时,不用发版就能把实验往回滚

所以我们的做法是:把 OTA 变成自己的基础设施。

4. 我们愿意把预算花在 AI 抹不平的地方#

这部分我写的时候其实有点心虚——因为下面这些活,没有一个是「选对框架」白送的:

  • 聊天列表从倒置视图迁到 LegendList,逐条修流式追加时的尾随、飞入动画、气泡生长边界
  • 流式回复走原生 Markdown 渲染 + 增量 Shiki tokenizer(代码块边流边高亮)
  • 气泡元信息(时间 / 状态)几何:什么时候能跟在最后一行旁边、什么时候必须单独起一行,用原生测量的行矩形判定。流式期间 footer 的抖动我们是量过的——曾经出现 48 → 64 → 48 pt 的来回跳动
  • Android 预测性返回、edge-to-edge 渐变、手势冲突(比如「代码块自己在拖拽」那段)
  • 缓存优先启动 + 重连对账(SQLite),发送是乐观更新

为了不让「原生质感」变成口号,我们写了一页 Bubble Layout Acceptance:29 组固定 case × 2 个角色(用户/助手),加 12 档边界宽度,加 280pt 窄视口、深色/浅色、流式 start/pause/interrupt 全跑一遍;元信息要么整块在最后一行上,要么整块在下面一行——不允许盖住字符、链接和状态图标。这页清单里还老老实实写着一条:「这不是 Android 选择手势引起的滚动的修复」。

你看,这跟 Shopify 的 Helix 是同一个形状:改一行代码是秒级的,验证一个细节是小时级的。 差别只在语言,不在工作量。

三、OTA 这件事,值得单独展开#

这次讨论里几乎没人认真谈 OTA,但对我们它是决定性的。用一个我常用的比喻:

  • 原生层是「主厨」:他待在厨房(应用商店)里,换主厨要走很长的流程
  • JS 层是「食谱」:主厨按食谱干活,而食谱可以随时从网上递进去

对 Shopify 这种规模,流程的严谨性抵掉了 OTA 的诱惑——他们有完整的发布火车、灰度体系、稳定的团队编制,等几天审核不是问题。但对 99% 的初创团队,发布速度本身就是产品能力

所以我们把这件事做成了自己的:yaota(我们新开源的仓库),一个跑在 Cloudflare Workers 上的自托管 Expo OTA 服务。

它解决的问题很具体。我们之前用的是自己 fork 的一套 OTA 服务,越用越发现四个坑:

  1. 只有整包,没有二进制差分。用户每次更新都要下载完整 JS bundle,流量和等待时间都浪费在没变的部分上
  2. 签名能力弱:没有多应用独立密钥,也谈不上轮换和吊销
  3. 回滚靠手:出事时没有一条被验证过的回滚路径
  4. 指标不诚实:那个 download_count 其实统计的是「发出了多少次 manifest」,不是「多少台设备真的更新成功了」。用它做决策会骗自己

yaota 现在的样子:

  • 多应用、多频道:每个 App 独立的 channel / branch / release / 原生 runtime
  • 签名发布:RSA 签名、按 App 的密钥导入与轮换、资产完整性哈希、原生 fingerprint 校验
  • 内容寻址 + R2 去重:只上传缺失的 blob;SDK 57 默认支持 BSDIFF40,我们生成并验证二进制补丁,补丁不划算时自动回退整包
  • 发布控制:staging → promote → 按百分比放量 → 回滚(回滚是用新 UUID + 旧字节重发,而不是「删掉一个 release」——删掉不会把已经装上的版本变回去)
  • 一个能用的面板:HeroUI v3 的 dashboard,管密钥、管发布、管 App
  • CI 友好:一个可复用的 GitHub Action + TypeScript 发布器;main 分支 push 自动发 OTA

而且迁移过程我按「准生产」的要求走了:旧端点不动(已安装的原生 App 里写死了 URL,改仓库变量没用)、新服务先跑 canary channel、设备验收清单里包含「发布 A → 发布 B → 回滚 B → 设备启动的必须是 A 的字节」「没有基线的客户端必须能整包升级成功」「10% 放量在反复检查后不能把已经选中的客户端丢掉」这类条目。

是的,我们连自己家(当时几乎零用户)的 OTA 迁移都按 canary 流程走。 因为这条路上最容易骗的就是自己。

四、一张表:你的团队该怎么选#

把两本账抽象一下,我现在用这几个问题做判断:

条件更偏跨平台(RN 等)更偏原生
移动团队规模小团队,没有专职双端几十人以上,双端编制齐全
平台数量2 个3 个以上,或需要深度平台特性
工具链用 Expo 或同等内核已有强自建能力 / 愿意自建
OTA 的重要性高:发布速度是竞争力低:流程严谨可抵消
细节预算愿意投入「最后 1%」的验证工时同上(这条和框架无关)
AI 的用法用代理做翻译、验证、跨端对齐用代理把两套代码都变便宜

最后一行是我自己想加的:

AI 对两边的价值不一样,但没有偏袒任何一边。

  • 对跨平台团队:AI 最大的价值是「把一份意图落成两种实现」和「帮你验证原生细节」
  • 对原生团队:AI 最大的价值是「把写代码的成本压到两套代码可维护」

所以 AI 只是把权重从「写代码多贵」挪到了「你要的能力 + 你的组织形状」。Shopify 选了原生,因为他们要的是平台深水区的能力,而且付得起两套代码的长期账;我们选了 RN + Expo,因为我们要的是发布速度 + 一个足够好的手感,并且愿意把省下来的钱投进细节验证。

两种都不是错的。可怕的只有一种:照着别人的答案抄,不核对自己的条件。

最后#

Mustafa 那篇文章里有一句我非常认同:

Native is the right choice for Shopify now, but React Native was the right choice for Shopify in 2020.

我想接一句:React Native 也是我们在 2026 年仍然选它的原因——不是因为它便宜,而是因为我们把它当成一个可以按原生标准验收的产品技术栈,并且愿意为那个标准付出验证成本。

AI 让代码变便宜之后,产品的差距回到了那些不能便宜的地方:分发速度、细节的耐心、和对平台的尊重

我们的赌注是:在一个被认为「做不到原生质感」的技术栈里,把这些一条一条做出来

参考资料#

AI 没有杀死 React Native,它杀死了「省人力」这个理由
https://bangwu.me/posts/ai-didnt-kill-react-native/
作者
棒无
发布于
2026-09-15
许可协议
CC BY-NC-SA 4.0