技术全景与选型
客户端开发的第一课不是写代码,而是搞清楚要覆盖哪些"端"、为谁写、用什么写。本页先建立客户端技术版图,再给出选型决策框架——选型不是跟风,而是在「体验、成本、交付」三者里做显式取舍。
客户端版图
客户端 = 运行在用户设备上的软件,按载体大致分四类:
| 载体 | 代表 | 开发范式 | 分发途径 |
|---|---|---|---|
| 移动原生 | iOS(Swift/SwiftUI)、Android(Kotlin/Jetpack Compose) | 平台原生 SDK | App Store / Google Play / 国内应用市场 |
| 跨端框架 | Flutter、React Native、Kotlin Multiplatform | 一套代码多端复用(UI 或逻辑层) | 与原生相同 |
| 桌面 | Electron、Tauri、Qt、.NET MAUI | Web 技术栈或平台原生 | 官网下载 / 应用商店(macOS App Store、Microsoft Store) |
| 轻量载体 | 微信小程序、支付宝小程序、PWA | Web/小程序技术栈 | 宿主 App 内、浏览器 |
选择的第一原则:端越多,越需要一套统一的「共享逻辑」策略;端越少,越值得为每个端写原生。
技术栈谱系(2026 语境)
| 方案 | 语言 | UI 渲染 | 性能定位 | 生态成熟度 | 典型场景 |
|---|---|---|---|---|---|
| iOS 原生 | Swift | SwiftUI / UIKit(系统渲染) | 最高,深度贴合平台 | 官方一档 | iOS-only 或重体验产品 |
| Android 原生 | Kotlin | Jetpack Compose / XML | 最高 | 官方一档 | Android-only 或重体验产品 |
| Flutter | Dart | 自绘引擎(Impeller/Skia) | 高,跨端一致性好 | 移动 + 桌面 + Web 多端 | 强一致 UI 的跨端 App |
| React Native | TypeScript/JS | 原生组件(Fabric) | 高(逻辑在 JS,视图原生) | 社区大,JS 生态复用 | 团队已熟 JS/React 的跨端 App |
| Kotlin Multiplatform | Kotlin | 共享业务逻辑;UI 各端原生 | 逻辑共享、UI 原生 | 快速成长 | 希望共享逻辑又保留原生 UI |
| Electron | JS/TS + Node | Chromium | 中(内存/体积偏大) | 极成熟 | 桌面工具、IDE、企业应用 |
| Tauri | Rust + Web 前端 | 系统 WebView | 好(体积小、内存低) | 成长中(Tauri 2 稳定) | 轻量桌面应用、偏好 Rust 团队 |
| 小程序 | JS/TS | 宿主自渲染 | 受宿主限制 | 国内生态一档 | 微信/支付宝生态获客 |
选型决策框架:四个问题
Q1 平台覆盖:产品要上哪些端?
- 只上 iOS → 原生 iOS 几乎无争议;
- 只上 Android → 原生 Android;
- 同时 iOS + Android,团队已有 React/Vue 前端 → React Native 或 Flutter;
- iOS + Android + 桌面 + Web 都想要 → Flutter(覆盖广)或「共享逻辑 + 各端原生 UI」。
Q2 体验与能力深度:产品有多依赖平台能力?
- 重度依赖系统能力且要极致体验(相机算法、AR、后台音频、Watch/Widget)→ 原生,跨端框架走原生模块补差距的成本要计入;
- UI 以业务表单/列表/内容为主 → 跨端框架的收益远大于损失。
Q3 团队与技能栈:谁会长期维护?
- 团队全是前端 → React Native / Electron 学习曲线最缓;
- 团队会 Rust → Tauri、KMP 值得评估;
- 团队能招到原生双端 → 原生下限最稳(招聘面最广)。
Q4 交付与发布:频率、渠道、合规?
- 迭代快、需要热更新/灰度 → 注意 iOS 审核对动态下发代码的限制,跨端框架也不例外;
- 国内多市场分发 → Android 多渠道打包与签名管理是刚需(见打包签名与发布);
- 桌面端需要静默更新与签名 → Electron 生态最成熟,Tauri 正在补齐。
KMP 的边界(常被误解的一点)
Kotlin Multiplatform 的正确姿势:共享业务逻辑(网络、领域模型、存储、状态),UI 各端原生。它不是「一套 UI 处处跑」的替代品——想要一套 UI 选 Flutter;想要原生 UI + 不重复写业务逻辑选 KMP。它的短板正好是它的特点:每端 UI 仍要原生工作量,双端 UI 代码并不会显著减少。
跨端框架的内侧对比
| 维度 | Flutter | React Native |
|---|---|---|
| 渲染 | 自绘引擎跨端像素级一致 | 原生视图(iOS/Android 观感各自原生) |
| 语言/生态 | Dart,闭源小型生态,包多依赖 pub | JS/TS,直接复用 npm 与 React 生态 |
| UI 表达 | Widget 树,组合优于继承 | 组件 + 样式表,JSX |
| 原生桥 | MethodChannel / FFI | 新架构 TurboModule + JSI 同步调用 |
| 热加载 | 热重载/热重启(保持状态) | Fast Refresh |
| 性能瓶颈 | 首次构建、插件质量 | 大 JS bundle、原生边界调用 |
| 招聘/上手 | Dart 需新学 | 前端转岗成本最低 |
选 Flutter 的三个信号:需要跨端像素级一致的自定义 UI、团队愿意学 Dart、希望性能与一致性的上限高; 选 React Native 的三个信号:团队是 React/TS 栈、要复用大量 npm 生态、接受「两端观感各自原生」。
桌面方案的内侧对比
| 维度 | Electron | Tauri |
|---|---|---|
| 运行时 | 内置 Chromium + Node | 系统 WebView + Rust 内核 |
| 体积 | 典型安装包 80-150MB | 典型 5-15MB |
| 内存 | 每窗口一个渲染进程,偏高 | 复用系统浏览器内核 |
| 后端能力 | Node 全生态 | Rust(tokio 等),性能强 |
| 安全面 | 需自己收紧(nodeIntegration 等) | WebView 隔离 + 权限最小化设计 |
| 成熟度 | 生态工具链最全(electron-builder 等) | Tauri 2 已稳定,插件生态成长中 |
| 适用 | 需要 Node 生态 / 团队熟 JS | 追求小体积低内存 / 团队会 Rust |
落地:三层代码策略
无论选哪条路,架构上都应把代码分成三层:
- 业务逻辑层(语言无关的概念:状态、用例、规则)—— 尽量平台无关,这是未来「换壳」的资本;
- 平台适配层(存储、网络、系统能力封装)—— 接口在本层收敛,平台差异不得外溢;
- UI 层(页面与交互)—— 随方案走,尽可能薄。
判断是否成功分层:把 UI 层推倒重写(比如 Flutter 换 RN)时,业务逻辑层能否原样带走。能带走,分层及格。
常见坑速查
| 坑 | 现象 | 对策 |
|---|---|---|
| 为省钱跨端,低估平台深水区 | 相机/推送/支付每个都写原生插件,成本超原生 | 选型前把「能力缺口清单」列全再算总账 |
| 「一套代码三端」期望落空 | 桌面/平板适配、系统交互差异仍需逐端调 | 跨端解决 80% 的普通页面,10% 特殊场景仍要条件编译/插件 |
| 忽视 UI 一致 vs 平台一致之争 | 两端截图看似一致,iOS 用户觉得「不像 iOS」 | 明确视觉基线:品牌一致优先还是平台惯例优先 |
| 技术栈跟风迁移 | 每半年换个框架,业务逻辑层没搭好,全在重写 | 业务逻辑与 UI 解耦是「敢换框架」的前提 |
| 只算开发成本不算维护成本 | 上线后原生模块无人会改 | 把招聘/社区/官方支持周期计入选型表 |
| 版本锁死裸奔 | Flutter/RN 跨大版本升级成本高,长期不升积累技术债 | 立项就排「年度升级预算」,版本升级演练 |
检查清单
- [ ] 产品平台覆盖明确,每条端都有业务理由;
- [ ] 平台能力缺口清单列全并估算原生插件工作量;
- [ ] 团队技能栈与长期招聘面纳入决策表;
- [ ] UI 一致 vs 平台惯例的基线在团队内达成一致;
- [ ] 业务逻辑层已与 UI 解耦(换壳可带走);
- [ ] 排了框架版本升级预算,不是裸奔。
相关链接:iOS 开发 · Android 开发 · Flutter · React Native · 桌面应用 · 写作规范见客户端开发索引。