# 前端技术路线评估:Flutter / uni-app / uni-app x | 项目 | 内容 | | --- | --- | | 文档名称 | Continental Retail APP 前端技术路线评估 | | 文档版本 | V1.0 | | 编制时间 | 2026 年 08 月 | | 评估对象 | Flutter · uni-app · uni-app x | | 评估结论 | **推荐 Flutter** | | 外部数据核验日期 | 2026-08-25(来源见附录 A) | 文档控制信息 --- ## 0 结论摘要 **推荐 Flutter。** 这不是"哪个框架更时髦"的偏好问题。四条理由,每一条都可以查证: **第一,架构路线不同,能力上限就不同。** 跨端方案历史上分四条路线,uni-app 走的是"网页套壳",uni-app x 走的是"编译到系统控件",Flutter 走的是"自绘引擎"。这三条路线各有适用场景——**uni-app 系是为"一套代码同时发小程序 + H5 + App"设计的,而这个项目的目标恰恰是把六套小程序关掉,首版只发 Android 和 iOS。** 我们要付它的代价,收不到它的好处。 **第二,这个项目的原生能力密度非常高。** 扫码、VIN 识别、车牌识别、相机、相册、上传进度、定位、权限、弱网离线暂存、崩溃上报、埋点——这些不是画页面,是跟两个操作系统打交道。**这部分工作量不会因为换框架而减少一件。** **第三,生态不在一个量级,而且开放程度的差别在"开到哪一层"。** Flutter 主仓库 **91,171 次提交**,uni-app 主仓库 **11,216 次**,约 8 倍差距;fork 数 31,002 对 3,709,同样约 8 倍。更关键的是:Flutter 从渲染引擎到框架层全部 BSD 开源;uni-app x 的组件和 API 虽然也是 Apache-2.0 开源,**但真正决定 App 能力上限的 Runtime、SDK 和 HBuilderX 是 DCloud 自有知识产权,闭源,没有公开的提交历史。** **第四,构建链路和扩展能力受限,而"离线打包"这条退路并不是真正的退路。** 想用加密的付费插件,就只能云端打包;想做 Siri 快捷指令这类扩展,官方要求离线打包——**这两个要求互斥。** 更关键的是:离线打包给到的并不是一个可以随便改的原生工程,而是**围着 DCloud 闭源二进制(一组编译好的 AAR)搭起来的壳**,官方文档要求自定义 `Application` 必须继承 `DCloudApplication`,且写明「App离线SDK不支持Kotlin」。**你只能在壳外面加东西,改不了壳里面的东西。** **成本结论:首版投入两条路线基本持平,差异在 ±10% 以内。** 真正的差异不在首版人天,在**五年后**:需求持续增长、要接更多系统级能力时,一条路线的天花板是自己的工程能力,另一条的天花板是厂商插件市场里有没有人卖这个功能。 | 维度 | Flutter | uni-app | uni-app x | | --- | --- | --- | --- | | 架构路线 | 自绘引擎 | 网页套壳(WebView) | 编译到系统控件 | | 为谁设计 | 需要跨端一致性的独立 App | 小程序为主、App 为辅 | 小程序团队想做 App | | 界面一致性 | 两端逐像素一致 | 受各家 WebView 内核影响 | 用系统控件,两端有差异 | | 嵌 F6 网页 | 通道由 App 侧建立,**F6 零改动** | 同右 | **需 F6 引入 DCloud 的 JS 文件** | | 原生能力开发 | Pigeon 生成三端强类型代码,支持 CLI | 原生插件(已停止新增上架) | UTS 插件,**只能经 HBuilderX,不支持 CLI** | | 开源程度 | 引擎 + 框架全开源(BSD) | 框架层开源(Apache-2.0) | 框架层开源,**Runtime / SDK 闭源** | | 主仓库提交数 | **91,171** | **11,216** | 同左(含在 uni-app 仓库分支) | | 原生工程归谁 | **自己的工程**,Flutter 挂进去 | DCloud 的壳工程 | **DCloud 的壳工程**,核心是闭源 AAR | | App 扩展能力 | 标准原生开发,无额外规则 | 受限 | **小组件需 Xcode 做 .appex;Siri 需离线打包** | | 接入现有 GitLab 流水线 | 原生支持 | — | 结构性错配 | | 鸿蒙 | 社区分支,落后一段时间 | 支持 | **支持更完整**(这一项 uni-app x 更强) | | 首版成本 | 基准 | — | **±10% 以内,基本持平** | 三条路线总览。uni-app(传统版)几格标"—",是因为它在"界面本质上是网页"这一条上就已经不适合本项目,后续章节重点放在 Flutter 与 uni-app x 的对比。每一行的依据见第 1–5 章,外部数据来源见附录 A。 --- ## 1 市面上的跨端方案 ### 1.1 目前可选的技术栈 先把台面上的选项摆全,再谈取舍: | 方案 | 出品方 | 语言 | 首次发布 | 现状 | | --- | --- | --- | --- | --- | | **原生双端** | Google / Apple | Kotlin · Swift | — | 平台官方方案,能力无上限 | | **Flutter** | Google | Dart | 2017(1.0 于 2018 年底) | 跨端主流方案,生态最大 | | **React Native** | Meta | JavaScript / TypeScript | 2015 | 成熟,适合已有 React 团队 | | **uni-app** | DCloud | Vue + JS | 2018 | 国内多端方案,小程序场景占优 | | **uni-app x** | DCloud | UTS + UVue | 2023 | uni-app 的原生渲染重构版 | | **Taro** | 京东 | React / Vue | 2018 | 重心在多家小程序平台 | | **Kotlin Multiplatform** | JetBrains | Kotlin | 2020 | 逻辑层共享强,UI 层生态尚浅 | | **.NET MAUI** | Microsoft | C# | 2022 | 微软栈企业适用,国内生态薄 | | **原生 + H5 混合** | — | 任意 | — | 老牌做法,性能与体验受限 | 市面上主要的跨端方案。前五个是本次讨论真正需要展开的。 ### 1.2 归纳:其实只有四条架构路线 上面九个方案,剥掉品牌和语言的差异,底层只有四条路线。**理解了这四条,就能理解为什么不同方案的能力上限不一样:** ``` ① 原生双端(Native) Android 工程师 ──写一遍──▶ Kotlin ──▶ 安卓系统的按钮 / 列表 / 输入框 iOS 工程师 ──写一遍──▶ Swift ──▶ 苹果系统的按钮 / 列表 / 输入框 → 两套代码、两套人,但系统给什么就能用什么,没有天花板 ② 网页套壳(uni-app、原生 + H5 混合) 一套 Vue 代码 ──▶ JavaScript ──▶ 系统自带的浏览器组件 ──▶ 渲染成网页 → 一套代码,但用户看到的本质上是个网页; 要用系统能力,得靠"插件"从网页世界打一个洞出去 ③ 编译到系统控件(uni-app x、React Native) 一套代码 ──编译──▶ Kotlin ──▶ 安卓系统的原生控件 ──编译──▶ Swift ──▶ 苹果系统的原生控件 → 一套代码,用户看到的是真正的原生控件。 代价:中间那本"翻译词典"必须够全, 词典里没有的东西就做不出来,得自己去补词条 ④ 自绘引擎(Flutter) 一套 Dart 代码 ──▶ Flutter 自带引擎,自己画出每一个像素 ──▶ 屏幕 → 一套代码,不用系统的任何控件,两端画出来完全一样 ``` 用装修打比方: - **① 原生双端**:请两个装修队分别装两套房子。质量最好,花两份钱,而且两边多半装得不太一样。 - **② 网页套壳**:在两套房子里各贴一层一模一样的壁纸。快、便宜,但墙还是人家的墙——墙有多平,壁纸就有多平。 - **③ 编译到系统控件**:拿同一张图纸,翻译成两家各自的材料清单,再让两个装修队照做。比贴壁纸结实得多。**但图纸上画了个东西、翻译词典里没这个词,就做不出来。** - **④ 自绘引擎**:自己带整套施工队和材料进场,从水泥开始砌。不管进的是哪套房子,装出来完全一样。 ### 1.3 四条路线的能力上限不一样 这是本章最重要的一句话,也是后面所有结论的地基: | 路线 | 界面一致性 | 系统能力的获取方式 | 能力天花板由谁决定 | | --- | --- | --- | --- | | ① 原生 | 差(两端天然不同) | 直接调 | **无天花板** | | ② 网页套壳 | 差(受内核影响) | 靠插件从网页打洞出去 | **插件生态有没有人做** | | ③ 编译到控件 | 中(用系统控件) | 靠"翻译词典" + 插件 | **词典覆盖度 + 插件生态** | | ④ 自绘引擎 | **最好(逐像素一致)** | 自己写原生插件直接调 | **自己的工程能力** | 四条路线的对比。最后一列是本项目最该关注的:**②③ 的天花板在别人手里,④ 的天花板在自己手里。** 一个五年周期的业务系统,需求只会越加越多。天花板在谁手里,是个战略问题,不是技术偏好。 --- ## 2 Flutter 与 uni-app / uni-app x 的对比 上一章讲了四条路线。这一章说清楚这三个具体方案分别是哪条路线、为谁设计、适合什么。 ### 2.1 uni-app:第 ② 条路线,为小程序团队设计 **它是什么**:用 Vue 写代码,在 App 端跑在系统自带的浏览器组件里。 **它为谁设计**:DCloud 的出发点非常明确——让**已经在做微信小程序的前端团队**,用同一套 Vue 代码顺便发一个 App 和一个 H5。 **它适合什么场景**:主战场是小程序、App 只是顺带的项目。比如一个商城,微信小程序是主入口,App 只是给老客户的一个补充。这类项目 uni-app 的价值非常大。 **它不适合什么**:App 是主战场、且需要大量系统能力的项目。因为界面本质上是网页,要用相机、要扫码、要后台上传,都得靠插件从网页世界打洞出去。 ### 2.2 uni-app x:第 ③ 条路线,是 uni-app 的重构版 **它是什么**:用一门叫 UTS 的新语言写,编译成安卓的 Kotlin、苹果的 Swift、鸿蒙的 ArkTS,渲染用真正的系统原生控件。 **必须澄清一点:uni-app 和 uni-app x 不是同一个东西的两个版本,是两套不同的技术底座。** 它们共享品牌、共享 IDE、共享很多写法,但底层是重写的。一个直接证据:**uni-app x 不支持传统 uni-app 的原生插件,而那批旧原生插件已经停止接受新增上架。** 即使在 DCloud 自家体系内做版本迁移,插件也要重写。 **设计思想值得肯定**:UTS 直接编译成 Kotlin 和 Swift,比"字符串方法名 + 弱类型参数"的传统桥接方式要优雅得多。**这一点应该如实承认。** **它为谁设计**:还是那批小程序团队,只是这次要把 App 端做得更像原生。 **它的约束在哪**:见 1.3 那张表的第 ③ 行——能力天花板取决于"翻译词典"的覆盖度和插件生态。词典里没有的、插件市场上没人卖的,就得自己用 UTS 补,而补这件事又受工具链约束(第 5 章)。 ### 2.3 Flutter:第 ④ 条路线,为独立 App 设计 **它是什么**:Dart 代码提前编译成机器码,界面由 Flutter 自带的引擎逐像素绘制,不使用系统的任何控件。 **它为谁设计**:出发点就是**做一个正经的 App**,而不是"顺便也发一个 App"。 **这带来两个结构性结果**: 1. **界面完全脱离系统控件的差异** —— 同一套设计规范在 Android 和 iOS 上落地的结果逐像素一致。 2. **原生能力靠标准插件机制直接对接** —— 每个能力封装成独立插件包,接口用官方工具从一份定义文件生成 Dart / Kotlin / Swift 三端强类型代码,改了接口忘记同步实现,**编译期就报错**。要什么能力就自己写,不用等插件市场。 ### 2.4 三者的定位对照 | | uni-app | uni-app x | Flutter | | --- | --- | --- | --- | | 架构路线 | ② 网页套壳 | ③ 编译到系统控件 | ④ 自绘引擎 | | 原始设计目标 | 小程序团队顺便发 App | 小程序团队把 App 做好一点 | 做一个独立的正经 App | | 主平台 | 小程序 / H5 | 小程序 / H5 / App | **App** | | 界面一致性 | 弱 | 中 | **强** | | 系统能力获取 | 插件打洞 | UTS 插件 + 翻译词典 | **自写原生插件,直接调** | | 能力天花板 | 插件生态 | 词典 + 插件生态 | **自己的工程能力** | | 适合本项目吗 | 否 | 部分适合 | **适合** | 三个方案的定位差异。最后一行的判断依据在第 3 章。 ### 2.5 架构层面的结论 **这个项目要做的是一个独立 App,不是一个小程序的附属品。** 它的目标是把六套微信小程序整合掉、关停,首版只发 Android 和 iOS,不发小程序、不发 H5、不发鸿蒙。也就是说: > **uni-app 系最值钱的能力——"一套代码同时发小程序、H5 和 App"——在这个项目里没有买家。** 我们要承担它为了多端兼容而付出的所有架构代价(能力天花板受制于插件生态、工具链绑定、构建方式受限),却收不到它最大的那份好处。 **单从架构选型的角度,在这个项目上 Flutter 已经胜出。** 后面三章是把这个结论落到具体的业务需求、生态数据和工程链路上。 --- ## 3 技术评估:结合本项目的业务需求 > 这一章写给技术评审。 ### 3.1 嵌入 F6 网页与双向通道 —— 本项目最高风险项 这个 App 里最核心的几条业务链路——报价开单、施工查车、结算收银,以及整个提醒模块——是把 F6 的网页嵌进 App 里承载的。这些网页需要调用 App 的能力(扫码、拍照、相册、带进度的上传、拨号、获取登录态与门店上下文、原生弹窗、跳转原生页等,共 13 项能力、15 个方法),App 也要能反向通知网页。 ``` 【Flutter 方案】F6 页面不需要任何改动 ──────────────────────────────────────────────── F6 的网页 │ window.ContiBridge.call('scan', { mode: 'barcode' }) │ ▲ │ └── 这段胶水代码,由 App 在页面加载完成时自动注入 ▼ 单一双向通道(JavaScript Channel) │ ▼ App 的 WebView 容器 ──▶ 原生扫码 / 相机 / 上传 一条通道,双向,收发同一套协议:{ id, method, params } 【uni-app x 方案】F6 页面必须先引入 DCloud 的 JS 文件 ──────────────────────────────────────────────── F6 的网页 │ ⚠ 必须先引入: