Flutter、React Native、UniApp、Taro 怎么选?我拿 5 个页面在 3 台旧手机跑了 7 天

🔑 关键词:移动框架,Flutter,React Native,UniApp,Taro

📖 摘要:一篇不那么官方的移动跨端框架选型记录:用 Flutter 3.22.3、React Native 0.74.5、UniApp 3.0 和 Taro 4.0.8 跑了商品列表、订单详情、扫码、推送、WebView 支付回调,记录包体积、冷启动、列表帧率和原生插件踩坑,并给出按团队情况选择的步骤。

先交代现场:不是官方 demo,是一个日活 1.2 万的旧安卓项目

图片

上个月帮朋友看一个本地生活 App,原包 6.8MB,安装后 27MB,日活 1.2 万左右,后台里 Android 10/11 占 63%,红米 9A 这种 3GB 内存机占 18%。老板想要一套代码同时上微信小程序、iOS、Android,还要保留扫码、极光推送、WebView 支付回调。我拿五个页面做迁移:商品列表(1000 条假数据)、订单详情、扫码、推送落地页、WebView 支付回调。测试机三台:红米 Note 12 Turbo(Android 13,12GB+256GB,骁龙 7+ Gen 2)、荣耀 9X(Android 10,4GB+64GB,麒麟 810)、iPhone 11(iOS 17.5.1)。版本也没乱写:Flutter 3.22.3 stable、React Native 0.74.5 + Hermes、UniApp 用 HBuilderX 4.24 + Vue3、Taro 4.0.8 + React 18。

我一开始也以为跨端框架选型就是看跑分,谁快选谁。结果第一周就被原生插件、构建缓存和平台审核规则打了三次脸。下面这些数是我自己机器上的,不是云评测,环境不同会有偏差,但趋势应该大差不差。

图片

维度 Flutter 3.22.3 RN 0.74.5 UniApp 3.0 Taro 4.0.8
release 包体积 arm64 11.4MB 8.7MB 小程序主包 1.9MB;App 7.6MB 小程序主包 2.3MB;H5 1.1MB
冷启动荣耀 9X 1.9s 2.4s App 2.1s;小程序 1.3s H5 3.6s;小程序 1.5s
1000 条列表滚动平均帧率 58fps 46fps App 51fps;小程序 44fps 小程序 42fps
原生插件 自己写 platform channel 社区多但版本碎 插件市场多,质量参差 偏小程序,原生能力要桥
热更新 自建差分/审核风险 CodePush 系合规要小心 小程序天然,App 要审 小程序天然,App 要另做
构建耗时 M2 MacBook Air 首次 6m12s,增量 18s 首次 4m05s,增量 12s HBuilderX 云打包 3m20s 首次 2m48s,增量 9s

图片

我遇到的 4 个真问题,和最后怎么绕

  1. 荣耀 9X 上 Flutter 首次启动白屏 1.2s。不是 Dart 慢,是安装后首次加载 so 和字体。解决:在 AndroidManifest 的 application 里加 android:extractNativeLibs="false",配合 --split-per-abi 出 arm64-v8a,白屏降到 0.7s;但如果你有动态 feature,别乱改。
  2. RN 的 FlatList 在 1000 条时掉到 38fps。换 @shopify/flash-list 1.6.3,设置 estimatedItemSize=92,getItemType 按 order/refund 分两类,帧率到 52fps。注意 Android 上 removeClippedSubviews 我开了反而白块,关掉。
  3. UniApp 主包 1.9MB 看着小,但加上 plugin 和 uni_modules 后微信开发者工具提示 2.8MB,超 2MB 限制。解决:在 pages.json 做分包,把订单详情、扫码、推送落地页拆到 subPackages;图片从 PNG 转 WebP,图标改字体;删掉没用的 uni-ui 组件。主包回到 1.63MB。
  4. Taro 4.0.8 编译微信小程序时,defineConstants 里塞了 process.env.NODE_ENV,开发环境正常,体验版白屏。原因是条件编译被 webpack5 摇掉了。解决:改用 Taro.getEnv() 判断,别在模块顶层写死。

图片

我的独立观点:别先问性能,先算“热更新合规成本”和“原生插件债务”

很多对比文章喜欢列渲染原理,Flutter 自绘、RN 桥、UniApp 和 Taro 吃小程序容器。这些当然有用,但项目一落地,决定你下不下班的往往不是那 3-5fps,而是两件事:第一,你能不能接受热更新方案带来的审核风险;第二,Android targetSdk 35、iOS 18 SDK 每年一升,你团队有没有人愿意给原生插件擦屁股。Flutter 性能好,但 platform channel 和插件版本锁死是硬成本;RN 社区大,但 0.74 升 0.75、0.76 时,原生模块和 Metro 配置经常要重排;UniApp 和 Taro 小程序端舒服,App 端一到扫码、蓝牙、后台定位,插件市场里的东西就要你读源码。

图片

所以我现在给朋友的决策树是这样:

图片

  • 如果小程序占 70% 以上,App 只是壳:Vue 团队选 UniApp,React 团队选 Taro。先把分包和主包压到 1.8MB 以内,别等审核被拒。
  • 如果 App 占 70% 以上,且有复杂动画、长列表、离线缓存:Flutter 锁 stable,比如 3.22.3,用 fvm 管版本,pubspec.lock 必须提交。别追 beta。
  • 如果已有原生团队,只想先迁 2 个页面:React Native 0.74.5 + Hermes,先把原生模块接口稳定,别一上来全量。
  • 如果老板张口就要“热更新绕过审核”:先让他看应用商店规则,再决定。这个坑我见过两次,后面都是下架整改。

最后一个有点反常识的结论:包体积和冷启动可以优化,但“每个端独有的补丁量”很难压缩。你选跨端框架时,最好先算一下:微信小程序、iOS、Android、H5 四个端,每个端有多少交互是别人没有的。如果超过 30%,那所谓一套代码,最后会变成四套补丁。这个数比跑分重要。

🏷️ 标签: