本节摘要:选型不是给框架打总分,而是在渲染机制、语言栈、发布能力、人才结构四个维度上找「与你项目约束匹配的短板组合」。本节把原生双轨、Flutter、React Native 摆在同一张桌上,用完整案例演示一次可复盘的选型决策,并给出何时坚决不该选 RN 的反面清单。结论将直接决定 1.3 节你用哪条命令初始化项目。
承接上一节的原理光谱,现在把光谱两端与中间的代表请到同一张桌上。先说一个反例:某团队因为「招聘容易」选了跨平台方案,产品却是一个重度依赖相机实时滤镜与蓝牙外设的工具应用,结果一半功能都要写原生模块桥接,跨平台节省的工作量被桥接维护成本吃掉大半。这个案例的教训不在于选错了框架,而在于选型时只看了「人才」这一个维度。跨平台方案都是「短板组合」:每种方案都有自己天生费力的场景,选型的本质是确认你的项目恰好不长在那个费力场景上。
先把三条路线的机制差异说清楚,这是所有对比的底层。原生双轨是「两套人马各自施工」:iOS 用 Swift 配 UIKit 或 SwiftUI,Android 用 Kotlin 配 Jetpack Compose,性能与平台能力零折扣,代价是业务逻辑写两遍、版本节奏对两遍。Flutter 是「自带建材的施工队」:Dart 语言配自绘引擎 Skia(及其后继 Impeller),界面完全不依赖系统控件,因此两端像素级一致、动画流畅,代价是包体更大、与原生控件体系隔了一层。React Native 是「雇本地工人的总包方」:JavaScript 与 React 描述蓝图,两端原生控件负责施工,原生质感与 Web 生态兼备,代价是必须管理两端行为差异与桥接层的复杂度(新架构已大幅缓解,但心智模型仍在)。

文字版浓缩成一张表,方便你在选型会上直接引用:
| 维度 | 原生双轨 | Flutter | React Native |
|---|---|---|---|
| 界面一致性 | 两端各自为政 | 像素级一致 | 高度一致但保留平台差异 |
| 复杂动画性能 | 最好 | 很好 | 好,动画密集场景需调优 |
| 业务逻辑成本 | 写两遍 | 一遍 | 一遍 |
| 接入平台专有能力的成本 | 零 | 写插件 | 写桥接,新架构下更顺 |
| 包体积 | 最小 | 偏大 | 较小 |
| 热更新 | 基本不可行 | 受限 | JS 层可行,两端政策不同 |
背景:一家电商公司的详情页团队,存量应用是原生双轨,需求方要求详情页改版迭代提速,两周一版变成一周一版;团队有六名前端背景工程师熟悉 React,两名原生工程师维持壳工程。操作过程如下:先把改版范围圈定为商品主图、规格面板、评价楼层与购买栏,确认不涉及相机、蓝牙等重度设备能力;再用 1.1 节的原理判断这个页面的性能敏感点在图片流与手势交互,属于通信密集而非计算密集,恰好是 RN 的舒适区;然后评估发布节奏,发现 Android 侧的热更新能力能把「紧急文案修正」的审核等待从按天计压缩到按小时计,iOS 侧虽然必须走商店审核,但 JS 包内的改动已能覆盖大多数需求;最后盘点人才,六名 React 工程师直接转入,两名原生工程师负责壳工程与未来的原生模块。
结果:详情页单独用 RN 重写并嵌入原生应用,一个季度后迭代周期稳定在每周一版,滚动性能经第 6 章方法调优后达标。解读:这个案例成立的根基是「页面级混合」策略——不是全应用切换技术栈,而是把新代码写到 RN 容器里,与原生共存。变式:假如需求方要的是全应用级重构,同样的分析会得出不同结论,因为全局迁移要背上导航体系、启动性能与团队转型的三重成本,需要重新开一次选型会。选型结论永远跟着「范围」走,脱离范围谈框架优劣都是空谈。
反面清单同样重要,三种情形建议直接排除:其一,应用核心是重度图形渲染(滤镜流水线、实时视频特效),此时自绘或原生才是主场;其二,团队没有任何原生工程师且产品强依赖平台专有能力的深度定制,桥接层的维护会变成单点风险;其三,产品要求两端体验完全一致且视觉复杂度极高,RN「尊重土壤」的哲学反而成了负担。另外提醒一句:评估时别只用官方示例测手感,示例永远长在框架的舒适区里;拿你自己业务里最刁钻的那个页面做原型,结论才可信。
下面这段「选型评分卡」脚本把本节方法固化下来,团队可以照着填:
// 选型评分卡:每项 1 到 5 分,5 表示「该维度与本项目高度匹配」 const scorecard = { // 团队现有技术栈与哪条路线的迁移成本最低 teamStackMatch: { native: 2, flutter: 2, reactNative: 5 }, // 项目的性能敏感点:计算与图形密集打低分,通信与表单密集打高分 performanceProfile: { native: 5, flutter: 5, reactNative: 4 }, // 是否依赖大量平台专有能力:依赖越多,桥接型方案越吃亏 nativeCapabilityNeeds: { native: 5, flutter: 3, reactNative: 3 }, // 发布节奏压力:需要热更新与高频迭代时 RN 占优 releaseCadence: { native: 2, flutter: 3, reactNative: 5 }, // 双端体验一致性要求:要求像素级一致时自绘占优 uiConsistencyDemand: { native: 3, flutter: 5, reactNative: 4 }, }; function decide(scorecard, weights) { const totals = {}; for (const route of ['native', 'flutter', 'reactNative']) { totals[route] = Object.keys(weights).reduce( (sum, dim) => sum + scorecard[dim][route] * weights[dim], 0 ); } return Object.entries(totals).sort((a, b) => b[1] - a[1]); } // 权重按项目实际调整;输出各路线加权总分与排名 console.log(decide(scorecard, { teamStackMatch: 3, performanceProfile: 2, nativeCapabilityNeeds: 2, releaseCadence: 4, uiConsistencyDemand: 1, })); // 输出:reactNative 57 分居首,flutter 45 分次之,native 43 分垫底
评分卡的价值不在分数本身,而在逼着团队把「我们到底在意什么」写成带权重的显式参数——争论权重的过程,往往比看结果更有收获。
决策落定,下一节进入动手环节:把环境装好、把项目建出来,让双端的第一屏亮起来。