技术笔记
原生还是跨端:移动交付踩出来的取舍
Swift、Objective-C、Kotlin、Dart 四条技术线都有真实交付工程的人,怎么回答「原生还是跨端」?讲取舍逻辑,不讲信仰,附判断外包交付是不是真原生的核验项。
文中客户一律用描述性别名,不出现客户名称。
「原生还是跨端」这个问题,几乎每个要做 App 的甲方都问过。网上的答案通常站队:要么「跨端天下第一」,要么「非原生不可」。我们不想站队——我们的仓库里,Swift、Objective-C、Kotlin、Dart 四条技术线都有真实交付的工程,加起来是数十个原生/移动仓库;另有 Xcode 工程和多个 Android/Flutter 工程在本地可核验,多个 iOS App 已在架。两条路都真金白银走过,所以这篇讲的是取舍逻辑,不是信仰。
一、四条语言线,各自服务什么场景
先把我们自己的分布摆出来:Objective-C 仓库最多,Swift 其次,Dart(Flutter)和 Kotlin 各占一块。这个分布不是随机的,对应着几类典型场景:
- 深度调用设备能力的项目走原生。3D 扫描 App 用 Swift 原生写,因为要直接操作深度相机、触觉反馈和渲染;相机采集类 App 里连权限判断都写在原生层。这一层用跨端方案不是不行,是调试成本会反噬收益。
- 内容型、展示型的 App 两条路都行。我们用 Dart 交付过设备编目和影音内容类产品,也用原生交付过同类形态的产品——这类项目选型主要看团队和长期规划,不是技术优劣。
- 老工程的延续线在 Objective-C。相当一批存量 iOS 工程是 ObjC 的,继续演进、二开、组件化改造(我们做过 CTMediator 系列的本地组件拆分)都发生在这一线上。「新项目才用 Swift」不等于「ObjC 工程该推倒」。
二、判断维度:四个问题问下来,答案基本就出来了
- 设备能力调用有多深? 只用网络、定位、推送,跨端完全够;要碰相机流、深度数据、蓝牙底层、实时渲染,原生层绕不开。判断方法是列出 App 用到的系统能力清单,看有多少落在「跨端插件质量参差」的那一类。
- 这个 App 要活几年? 生命周期短的运营型产品,跨端的开发效率优势能兑现;要做五年、要传给后来人维护的产品,原生工程的可读性和工具链稳定性更值钱——Flutter 框架版本升级带来的迁移成本,也是长期成本的一部分。
- 团队交接怎么发生? 接手的人好招吗?iOS/Android 各配一人还是招一个跨端全干?不少甲方选跨端的真实原因是「只有一个人的预算」,这没问题,但要清楚代价:单点依赖。
- 既有工程是什么语言? 已有 ObjC 工程要加功能,新模块用 Swift 混编是常规操作;已有原生工程里塞一块 Flutter,就要处理混合栈的路由和状态管理。选型不是从零开始选,是在现状里选。
三、怎么判断外包交付的是「真原生」还是套壳
这是甲方最容易吃亏的地方。真原生工程和套壳网页包,在交付物上差别是藏不住的,验收时逐项核:
- 要工程文件,不要安装包。真原生交付会包含
.xcodeproj/.xcworkspace(iOS)或完整 Gradle 工程(Android),套壳包拿不出这些,或拿出来结构空洞。 - 看依赖清单。真原生工程有
Podfile(iOS CocoaPods)或build.gradle依赖树,第三方库一目了然;套壳包的核心「依赖」往往是一个内嵌浏览器内核。 - 抽查系统能力调用代码。比如相机权限,真原生工程里能找到对应的权限判断实现;套壳包里只有网页的授权弹窗。
- 看模块划分。真原生工程按业务拆模块、拆组件,能对上需求文档;套壳包通常一个壳工程加一堆 H5 资源目录。
我们自己的交付里这些都经得起翻:Xcode 工程逐个打开能看、依赖能查、权限代码能定位到具体文件和行号。反过来讲,这也是甲方验收时可以直接照抄的清单。
写在最后
原生还是跨端,本质是拿「开发效率」和「能力深度、长期成本」做交换。没有全对的答案,只有错配的答案:把五年期、重设备能力的产品交给跨端,把三个月的运营活动做成双端原生,都是错配。选型时把上面四个问题过一遍,多数分歧会自己消掉。
如果你正在为选型纠结,欢迎把你的场景和设备能力清单发给我们,按四个维度一起过一遍再定。