跨端 App 和原生 App:我现在会怎么选技术栈

这篇记录一下我最近看移动端技术栈时的判断。

起因很简单:路图现在是微信小程序 + Bun/Hono 后端,已经能跑在微信里的 iOS 和 Android 上。但如果哪天要做一个真正能上 App Store、安卓应用市场的独立 App,到底该用跨端,还是老老实实写原生?这个问题不能只用一句“跨端省时间”或者“原生性能好”糊弄过去。

我现在的结论是:

原生 App 买的是平台能力和上限;跨端 App 买的是迭代速度和团队复用。选哪个,不是信仰题,是产品阶段题。


先把概念分清楚

所谓“原生 App”,一般是:

  • iOS:Swift + SwiftUI / UIKit + Xcode
  • Android:Kotlin + Jetpack Compose / View System + Android Studio

也就是说,iOS 和 Android 各写一套客户端。它们可以共享后端、接口协议、设计系统、业务规则文档,但 UI 和客户端工程基本是两份。

所谓“跨端 App”,常见技术栈是:

  • React Native / Expo:TypeScript / JavaScript 写业务,渲染成原生组件或调用原生能力。
  • Flutter:Dart 写业务,Flutter 自己负责渲染 UI,跨 iOS、Android、Web、桌面。
  • Kotlin Multiplatform:Kotlin 共享业务逻辑,UI 可以继续各平台原生,也可以用 Compose Multiplatform 共享一部分 UI。
  • Capacitor / Ionic:Web 技术栈外面包一层原生容器,适合 Web-first 团队。
  • .NET MAUI:C#/.NET 体系里的跨端方案,适合已有 .NET 团队。
  • Taro / uni-app:在中文生态里很常见,尤其适合小程序、H5、App 一起考虑的业务。

它们都叫跨端,但实际差很多。React Native 和 Flutter 是“移动 App 主战场”的跨端;Capacitor 更像“Web App 进 App 壳”;KMP 更像“共享业务逻辑但保留原生体验”;Taro/uni-app 则更贴近“小程序多端投放”。


原生技术栈:上限最高,但成本也最实在

iOS 原生

主流栈是 Swift、SwiftUI、Xcode。Apple 官方现在的叙事也很清楚:用 Xcode 管开发、测试、分发,用 SwiftUI 以更少代码构建 Apple 全平台界面。

优点很直接:

  • 平台能力最完整。相机、相册、定位、推送、后台任务、Widget、Live Activities、Apple Watch、Vision Pro,都是第一时间吃到官方能力。
  • 体验最贴平台。导航、手势、权限弹窗、动画节奏、系统控件,不需要反复模拟。
  • 调试和性能工具完整。Instruments、Xcode profiler、系统日志、崩溃符号化,这些都是正统工具链。
  • 长期维护更稳。系统 API 变了,官方文档和迁移路径通常最清楚。

缺点也很现实:

  • 只能覆盖 Apple 平台。Android 还得另写一套。
  • 团队门槛更高。Swift、Xcode、证书、Provisioning Profile、App Store 审核,这些都要熟。
  • 产品早期迭代慢一些。尤其一个人同时维护 iOS + Android,很容易变成“今天修 iOS,明天补 Android”。

Android 原生

主流栈是 Kotlin + Jetpack Compose + Android Studio。Google 官方文档已经把 Jetpack Compose 定位成 Android 现代 UI 的推荐工具,最近 Android 官方博客甚至用了“Compose First”这样的表达。

优点:

  • Android 平台能力最完整。后台服务、蓝牙、NFC、文件系统、Intent、系统分享、厂商通道,原生最方便兜底。
  • 性能上限高,尤其复杂列表、后台任务、系统级能力。
  • Kotlin + Compose 的开发体验比旧时代 XML + Java 舒服很多。
  • 和 Google / Firebase / Play Console / Android Studio 的工具链配合最好。

缺点:

  • Android 碎片化是真成本。不同系统版本、不同厂商 ROM、权限策略、后台保活、相册选择器,都会冒出来。
  • 只覆盖 Android。iOS 还得另写。
  • Gradle、依赖、构建缓存这些东西,状态不好的时候很磨人。

如果 App 的核心竞争力是“极致平台体验”或者“深度系统能力”,原生更像正路。比如导航、影像、专业创作、硬件连接、金融级安全、重度地图交互。


跨端技术栈:不是银弹,但很适合早期产品

React Native / Expo

React Native 的路线是用 JS/TS 写业务,调用原生能力。过去大家经常吐槽 bridge、原生模块、升级痛苦,但最近几年 New Architecture 已经成为主线,Expo 也把开发构建、云构建、提交商店、OTA 更新、监控这些流程包得越来越完整。

Expo 的关键变化是:不要再把它理解成“只能跑 Expo Go 的玩具”。官方现在推荐 production-grade 的 development build。简单说,它可以是你自己的开发版 App,能加自定义原生库,也能走 EAS Build、EAS Submit、EAS Update 这一套。

优点:

  • TypeScript 友好。对已有 Web / Node / Hono / zod / shared package 的项目特别香。
  • 生态大。地图、相册、分享、登录、支付、推送、埋点,大多数都有现成库。
  • 迭代快。表单、列表、生成进度、WebSocket、图片结果页这种产品,RN/Expo 写起来很顺。
  • 可以逐步下沉原生。遇到特殊能力,再写 native module 或用 config plugin。
  • AI 时代配套好。Expo MCP、React Native 调试工具、移动端自动化 MCP,都比较容易接进 agent workflow。

缺点:

  • 框架升级要跟。RN 大版本、Expo SDK、原生库兼容,是长期维护成本。
  • 复杂原生能力仍然要懂 iOS/Android。不是用了跨端就能完全不学原生。
  • 性能边界要注意。超复杂动画、重地图交互、大量原生 SDK 混用时,需要更谨慎。

Flutter

Flutter 的路线更“自成体系”:Dart 语言,Flutter 自己渲染 UI,目标是一个 codebase 覆盖 mobile、web、desktop、embedded。它的优势是 UI 一致、动画顺、组件体系完整,缺点是你要进入 Dart/Flutter 的世界。

优点:

  • 视觉一致性强。iOS/Android 上看起来很统一,适合强设计感产品。
  • 性能和动画体验好。很多场景下比 WebView 类方案稳。
  • 跨平台目标多。除了 iOS/Android,也能考虑桌面和 Web。
  • 工程体系完整,官方背书强。

缺点:

  • Dart 技术栈迁移成本。对于已有 TypeScript 项目,复用率没 RN 高。
  • 原生 SDK 接入也会遇到桥接问题。
  • UI 太一致有时反而“不够像平台”。这对某些工具型产品不是问题,对强平台感产品会是问题。

Kotlin Multiplatform

KMP 比较有意思。它不一定要求你“一套 UI 打天下”,更常见的用法是共享 domain/data/network/cache 等业务逻辑,然后 iOS 继续 SwiftUI,Android 继续 Compose。Google 和 JetBrains 现在都在推这条线。

优点:

  • 业务逻辑共享,但 UI 保持原生体验。
  • 适合复杂业务,比如离线缓存、同步、加密、规则引擎、订单计算。
  • Android 团队上手成本低。

缺点:

  • iOS 侧消费 Kotlin API 仍然有工程摩擦。
  • 团队要同时懂 Kotlin、Swift、Gradle、Xcode。
  • 对早期小团队来说,它解决的是“中后期复用问题”,不是最快出 Demo 的问题。

Capacitor / Ionic

这条路适合 Web-first 团队:先有一个 Web App,再用 Capacitor 包成 iOS/Android/PWA,同时通过插件访问原生能力。

优点:

  • Web 代码复用最大。
  • 后台管理、内容型、表单型、轻交互产品很快。
  • 如果本来就有成熟 Web 产品,上 App 成本低。

缺点:

  • 本质上还是 WebView 体验。复杂手势、性能、原生质感会有边界。
  • 重移动端交互时,后期可能要补很多原生插件。
  • 用户一旦期待“真正 App 手感”,WebView 感会暴露。

Taro / uni-app

中文生态里这两类很常见,尤其当目标是微信小程序、支付宝小程序、H5、App 多端投放时。对于“先小程序,顺手覆盖多端”的业务,它们有吸引力。

优点:

  • 小程序生态适配好,国内业务常见能力齐。
  • 一套代码打多个小程序平台,效率高。
  • Vue/React 团队容易上手。

缺点:

  • 做独立高质量 App 时,上限和调试体验不如 RN/Flutter/原生清晰。
  • 平台差异会漏到业务代码里。
  • 复杂原生能力还是绕不开插件和平台适配。

怎么选:我会用这张表

目标 优先技术栈 原因
极致 iOS 体验 Swift + SwiftUI 平台能力、审核、性能、系统集成最稳
极致 Android 体验 Kotlin + Jetpack Compose Android 官方主线,系统能力完整
一个小团队快速做 iOS/Android React Native + Expo TypeScript 复用高,工程和发布链路成熟
强视觉、强动画、跨移动和桌面 Flutter 渲染一致,UI 工具链完整
保留原生 UI,但共享复杂业务逻辑 Kotlin Multiplatform 共享 domain/data 层,不牺牲平台 UI
已有 Web 产品,想低成本进 App Capacitor / Ionic Web 复用最大,适合轻交互
小程序是主战场,多平台小程序投放 Taro / uni-app 国内小程序生态效率高

放到路图上,我倾向 Expo

路图这个项目现在的结构是:

  • 前端:微信原生小程序
  • 后端:Bun + Hono + TypeScript
  • 共享包:packages/shared 里放类型和 zod schema
  • 核心链路:提交目的地和偏好 → WebSocket 看生成过程 → 返回地图图片和结构化行程 → 保存/分享/历史记录

这个产品形态对跨端非常友好。它不是重度 3D,不是专业视频编辑,也不是后台定位导航。它最重要的是:表单体验、生成过程可视化、图片结果页、历史记录、分享保存,以及未来可能的会员/支付。

所以如果我要给路图做独立 App,我会这么走:

  1. 保留现有微信小程序,继续作为低摩擦入口。
  2. 新增一个 Expo App,不推翻后端。
  3. 复用 packages/shared 里的类型、schema、API 契约。
  4. 首版只做核心闭环:创建规划、WebSocket 进度、结果页、历史记录、保存图片。
  5. 等用户量和需求明确后,再决定哪些能力要下沉原生。

对路图来说,跨端不是为了“永远不碰原生”,而是为了先把 iOS/Android 的产品闭环跑出来。真遇到平台能力边界,再局部写原生模块。

这也是我现在看跨端最舒服的姿势:不要幻想它把平台差异消灭掉。它真正有价值的地方,是让早期产品把 80% 的通用体验先做出来,让团队把时间花在产品判断上,而不是一开始就在两套客户端工程里来回搬砖。


最后的判断

如果是“技术纯度”排序,原生永远最稳。

但如果是“一个真实产品从 0 到 1”排序,我会更看重团队已有栈、发布速度、后端复用、调试闭环和未来迁移成本。

我的粗暴版建议是:

  • 独立开发者 / 小团队 / TypeScript 后端:优先 React Native + Expo。
  • 设计驱动、动画多、愿意接受 Dart:Flutter 很强。
  • 已有 Android/Kotlin 团队,想兼顾 iOS:看 Kotlin Multiplatform。
  • 已有成熟 Web 产品:可以考虑 Capacitor。
  • 只追求平台上限:原生 SwiftUI + Jetpack Compose。

放到我自己的项目上,目前答案很明确:

路图先小程序跑通,再用 Expo 做独立 App。不要为了“跨端”而跨端,也不要为了“原生正确”一开始就背两套客户端。


参考资料

感谢您的收看 祝你天天开心~
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇