Files
conti-docs/tech-selection/前端技术路线评估-Flutter-vs-UniApp.md
T

61 KiB
Raw Blame History

前端技术路线评估: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 做 .appexSiri 需离线打包
接入现有 GitLab 流水线 原生支持 结构性错配
鸿蒙 社区分支(3.41 已发布,3.44 预计 9 月) 支持 一等公民(这一项 uni-app x 更强)
包体与内存 约多 10MB / 35MB 更小(这一项 uni-app x 更优,但本项目无包体 KPI)
首版成本 基准 ±10% 以内,基本持平

三条路线总览。uni-app(传统版)几格标"—",是因为它在"界面本质上是网页"这一条上就已经不适合本项目,后续章节重点放在 Flutter 与 uni-app x 的对比。每一行的依据见第 1–5 章,外部数据来源见附录 A。

表中"包体与内存""鸿蒙"两行是 uni-app x 占优的项,我们主动列出。 DCloud 官方另有一页专门对比 Flutter,客户方检索时大概率会看到——我们已把那一页逐条核验,结果见附录 C


1 市面上的跨端方案

1.1 目前可选的技术栈

先把台面上的选项摆全,再谈取舍:

方案 出品方 语言 首次发布 现状
原生双端 Google / Apple Kotlin · Swift 平台官方方案,能力无上限
Flutter Google Dart 20171.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 的网页
       │  ⚠ 必须先引入:<script src="uni.webview.1.5.5.js">
       │  uni.webView.postMessage({ data: {...} })
       ▼
   <web-view @message>                        (网页 → App,单向)

   uni.createWebViewContext(id).evalJS("...")  App → 网页,另一条单向通道)

   两条独立的单向通道,方向不对称

事实DCloud 官方 web-view 组件文档原文):网页要向 App 发消息,需要**"在网页中引入 uni.webview.1.5.5.js"**,再调 uni.webView.postMessage()App 向网页发消息走 evalJS(),本质是执行一段 JavaScript 字符串。

推论:这意味着 F6 这家第三方厂商,需要修改他们的页面,引入 DCloud 提供的 JS 文件。Flutter 方案下胶水代码由我们在 App 侧注入,F6 一行都不用改

F6 是这个项目里影响面最大的外部依赖——销售全链路、整个提醒模块、以及非马牌商品的采购供货都压在它上面。在这条链路上再叠一个"需要对方配合改造"的前置条件,是排期风险,不是技术偏好。

两点补充,避免结论被过度解读:

  • 这不是说 uni-app x 做不出 JSBridge。做得出,但要在两条不对称的单向通道之上,自己封装请求 ID、超时、就绪信号、错误处理、方法白名单这一整套;Flutter 的单一双向通道天然就是这个形状。
  • evalJS() 传大量数据要额外处理序列化和转义,上传进度这类高频事件走这条路需谨慎设计。

3.2 原生能力密度:本项目的决定性变量

能力 用在哪
扫码(条码 / 二维码) 扫码入库、扫码查件、商品与库位
VIN 识别 条码形式 + 印刷字符 OCR,端上完成
车牌识别 拍照上传走云端 OCR,需先压图
相机 检测报告、装车视频、鉴定证据
相册多选 证据上传、营业执照
文件上传(带进度) 大文件、弱网场景
图片压缩 上传前必须压,否则弱网传不动
拨号 客服、门店联系
定位 扫码入库以地图定位为准
运行时权限申请 相机、相册、定位,含拒绝后的引导
弱网离线暂存与幂等重传 断网本地存,恢复后批量提交且不重复
崩溃上报原生桥 Bugly 只有原生 SDK
埋点 SDK 接入 神策
安卓物理返回键拦截 嵌网页时不拦截会导致填一半的表单丢失
WebView 文件选择器 网页里的 <input type="file">
iOS 隐私清单 苹果强制要求,没有直接被拒

本项目需要的原生能力清单。门店场景(地下车库、仓库、施工区)网络条件差,而恰恰是这些场景要传大文件——弱网相关的几项不是可选项。

这张表是全文成本结论的支柱。 它说明这个项目的工作量重心本来就压在原生能力和系统集成上,"画页面快不快"能省下的比例有限。而上面每一项,在 uni-app x 下都是一个要自己写、自己维护、自己在两端分别验证的 UTS 插件——数量不会因为换框架而减少一件。

Flutter 侧:扫码这一个原生实现,同时服务 App 内的扫码页和嵌入网页的通道调用,一份实现两个调用方,不需要复制两套。

uni-app x 侧UTS 插件的设计思想更优雅,但按官方文档,UTS 插件目前只支持通过 HBuilderX 创建和使用,不支持通过命令行使用——后果见第 5 章。

3.3 崩溃上报与埋点

业务方指定了两个工具:崩溃用腾讯 Bugly,错误明细和埋点用神策。账号现成、合规口径已过,这个前提不因技术选型而改变。

Flutter uni-app x
神策 官方发布的插件,在公开包管理平台上,有认证发布者、有版本号 不在插件市场。官方说明因缺少 UTS 的压缩混淆方案暂未提供市场包,需联系技术顾问索取 zip 源码包;另有后端版本下限要求
Bugly 只有原生 SDK,需自建原生桥(几十行 Kotlin/Swift 未见官方支持,需完全自行用 UTS 封装

两个指定 SDK 的支持成熟度对比。

两边都有工作量,差别是 Flutter 侧有一项是公开发布、可版本化管理、有官方发布者背书的现成包;uni-app x 侧两项都是定制的,且其中一项脱离了公开的市场分发渠道——后续升级、问题追溯、责任归属都要靠人对人沟通,而不是查版本记录。

对一个要跑五年的系统,"崩溃上报本身不能再出问题" 是硬要求。

3.4 十九个模块并行开发时,边界怎么守住

这个项目 19 个业务模块、近三百条需求,会有多人并行开发很长时间。工程上最容易出问题的不是某个功能写不出来,而是模块边界慢慢烂掉——A 模块图省事直接引用了 B 模块的内部类,半年后想改 B 就动不了了。

Flutter 方案:用 Melos 组织 monorepo,21 个包按职责拆开(基础设施层 / 业务模块层 / 原生能力层),依赖规则由 Dart 的包机制在编译期物理强制——业务模块 A 根本 import 不到业务模块 B 的任何符号,不靠代码规范或口头约束。想复用组件,只能提到公共层。

uni-app x 侧同样可以做工程化拆分,但约束强度依赖团队自觉和评审纪律,缺少编译期的物理阻断。

这一条在项目初期看不出价值,在第二年会。

3.5 渲染性能、包体与内存(明确标注:非决定项)

Flutter 用自绘引擎、Dart 提前编译成机器码;uni-app x 编译成原生控件调用。两者在这个项目上都够用——这是一个以表单、列表、报表为主的业务 App,不是游戏,也不是有复杂动效的消费级产品。

拿性能说事经不起追问,我们不把它算进结论。 列在这里只是让对比完整。

包体与内存这两项,Flutter 确实更高,我们主动列出。 DCloud 官方对比页给出的实测是:安装包 18M 对 8.5M、内存占用约 138MB 对 103MB。这两个数字我们认为是可信的——自绘引擎要把渲染引擎打进包里,这是路线本身的代价,不是实现问题。

但它在本项目不构成决策变量:这是一个门店员工使用的内部业务 App,通过企业分发和应用商店安装,不参与消费级 App 的下载转化竞争,没有包体 KPI,也没有"多 10MB 就少一批用户"的场景。设备是门店配发的作业终端,35MB 内存差异在现代机型上不产生可感知影响。

需要一并说明的是,uni-app x 走离线 / 嵌入这条路同样有包体增量:按 DCloud 官方数字,iOS 约 8.7 MB、Android(仅 arm64-v8a)约 8.1 MB。这项对比的完整核验见附录 C

真正和体验相关、且在本项目真实存在的差异是视觉一致性:这个 App 要把六套来源不同、不同团队不同时期做的小程序整合成一个东西。整合最大的隐性风险不是功能缺失,而是同一个业务概念在不同页面上叫法不同、长得不同、操作方式也不同——用户会觉得"这还是六个东西,只是塞进了同一个壳子"。Flutter 逐像素自绘,同一套设计规范落地结果完全一致;uni-app x 用系统控件,安卓的按钮和苹果的按钮本来就不一样,要抹平需要额外工作。

3.6 小结

本项目的关键维度 Flutter uni-app x 差异是否决定性
嵌入 F6 网页 + 双向通道 通道由 App 侧建立,F6 零改动 需 F6 引入 DCloud 的 JS 文件
十几项原生能力 三端强类型生成,支持 CLI UTS 插件,只能经 HBuilderX
Bugly + 神策 神策有官方发布包 神策需单独索取;Bugly 无官方支持 较强
19 模块的工程边界 编译期物理强制 靠规范与评审 中等
视觉一致性 逐像素一致 需额外抹平 中等
渲染性能 够用 够用
包体与内存 约多 10MB / 35MB 更小 (内部业务 App,无包体 KPI

七个维度的逐条对照。最后两行特意列出,是为了说明我们没有把不构成差异的项算进结论里,也没有回避对方占优的项。


4 生态、社区、落地规模与 AI 工具链

这一章比大多数人以为的重要。技术栈的生命力不看今天能做什么,看社区每天往里投入多少。

4.1 开源程度:关键在"开到哪一层"

先澄清一个容易说错的点:uni-app x 不是闭源的。 它的组件和 API 大部分以 Apache-2.0 协议开源,在 dcloudio/uni-app 仓库的 uni-app-x 分支里。

但开源的层次不一样,这才是要害:

Flutter uni-app x
框架层(组件、API 开源(BSD-3-Clause 开源(Apache-2.0
渲染引擎 / Runtime 开源,在主仓库内 闭源DCloud 自有知识产权
原生 SDK 不适用(原生层完全由项目自己掌握) 闭源
开发工具(IDE 无绑定,任意编辑器 + 官方 CLI HBuilderX,闭源,且插件开发离不开它

开源层次对比。DCloud 的许可协议明确写明:内嵌的 Runtime 或 SDK 知识产权仍归 DCloud 所有。

这意味着什么: 当你遇到一个渲染层或运行时的 bug,Flutter 侧你可以读引擎源码、定位、提 issue、必要时自己 fork 修;uni-app x 侧你只能提工单等厂商。对一个五年周期的核心业务系统,这是两种完全不同的风险敞口。

4.2 社区活跃度:实测数据

指标 Flutter uni-app 倍数
主仓库提交数(默认分支) 91,171 11,216 约 8.1 倍
Fork 数 31,002 3,709 约 8.4 倍
Star 数 178,643 41,600 约 4.3 倍
仓库创建时间 2015-03 2018-07
开源协议 BSD-3-Clause Apache-2.0

GitHub 实测数据,核验于 2026-08-25,取自 flutter/flutterdcloudio/uni-app

口径要说明白,不做诛心解读: star 数反映的是全球开源关注度,不等于国内商业项目的落地数量。uni-app 在国内企业应用、商城、政企项目里的落地量非常大,这一点数据体现不出来。

但有一条差异是数据也遮不住的: Flutter 的 91,171 次提交包含了渲染引擎在内的全栈DCloud 的 11,216 次提交是框架层的,而真正决定 App 能力上限的 Runtime 和原生 SDK 闭源、没有任何公开的提交历史

也就是说,真实的工程投入差距比 8 倍这个数字看起来还要大——因为对方最核心的那部分,外界根本看不到,也无法参与。

另一个可查证的信号是平台连续性。 DCloud 在 App 端已经换过三代方案:5+ 应用 → nvue(基于修改过的 Weex 渲染引擎,而 Apache Weex 已于 2021 年 5 月退役、6 月仓库归档)→ uni-app x。DCloud 官方文档已说明 nvue 和 5+ 的官方维护在 2024 年停止,建议迁移到 uni-app x

对比 Flutter:2015 年至今同一条主线持续演进,没有让用户推倒重来过。这是"平台连续性"的差异,会直接变成五年后的迁移成本。

4.3 谁在用:可查证的落地规模

提交数说明的是"投入",落地案例说明的是"验证"。这里只列厂商官方渠道公开发布、可点开核对的,不引用二手传闻。

字节跳动是目前公开信息中规模最大的 Flutter 使用方(数据来自 Flutter 官方中文站的开发者故事,2026-06-22 更新):

  • 90 多款 Flutter 应用在线上运行
  • 800 多名 Flutter 开发者,并设有专职的 Flutter Infra 基建团队
  • 点名的产品包括:抖音火山版、飞书 Lark、Coze、小荷健康、幸福里、Lemon8,以及技术社区 掘金

原文对收益的表述是:「与原生双端开发相比,Flutter 为我们的团队节省了大约 1/3 的开发时间」

这个 1/3 必须标清口径:它的对照组是"原生双端",不是 uni-app。 拿它去论证"Flutter 比 uni-app x 省 1/3"是错的,我们不这么用。本文档的成本结论仍然是第 6.1 节那句——首版两条路线基本持平。这里引用它只说明一件事:一个有能力自研全套基建的团队,在做过 90 多个 App 之后仍然选择继续投入 Flutter。

顺带一提:这份评估里引用的技术社区"掘金",它自己的 App 就是 Flutter 写的。

uni-app x 侧,我们未检索到同等量级的公开大厂落地案例。 这里写"未检索到"而不是"没有"——DCloud 官方公布的是 uni-app 全系的开发者与应用总量,那个数字很大,但它统计的主体是小程序和 H5,无法单独拆出"用 uni-app x 做的独立 App"有多少、规模多大。口径不可比的数字我们不拿来对比。

4.4 AI 工具链:开放生态 vs 厂商内置

这是这次特别关注的一项。先说清楚:两边都有官方 AI 工具,不能说 uni-app x 没有。

Flutter / Dart uni-app x
官方 skills flutter/agent-pluginsdart-lang/skills独立开源仓库 内置在官方 uni-agent 助手中
官方 MCP 服务 Dart & Flutter MCP server uni-app-x-mcp
能用在哪些工具上 Claude Code、Codex、Cursor、Antigravity 等,装到哪个 agent 都行 主要围绕自家生态与少数几个工具
安装方式 npx skills add flutter/agent-plugins --skill '*'一行命令 随官方助手提供
能否自己改 / 自己加 可以,仓库开源,可 fork 可 PR 受限于官方提供

双方 AI 工具链对比。Flutter 的 skills 是任务粒度的,官方文档与 2026-05-06 的发布公告合计已列出十项以上,覆盖生成单元测试、生成集成测试、统计测试覆盖率、配置多语言、构建响应式布局、配置声明式路由、实现 JSON 序列化、解析包依赖冲突、修复静态分析错误、使用模式匹配等,仓库持续新增。

两个真实的差别:

① 开放 vs 内置。 Flutter 的 skills 是独立开源仓库,一行命令装进任意 AI 编程工具,团队可以 fork 它、按自己的规范改它、往里加自己项目的 skill。uni-app x 的 AI 能力主要绑在官方助手和自家 IDE 里——这和第 5 章要讲的工具链绑定是同一个问题的两面。

② 语料深度。 AI 生成代码的准确率和这门语言在公开代码里的沉淀量强相关:

  • Dart / Flutter:近十年公开代码沉淀在 GitHub 上,全球范围,各种项目形态都有。
  • UTS / UVue:新语言,语料以中文官方文档为主,体量小得多。而且插件市场的付费插件是加密分发的——这些代码根本不会进入任何公开语料。

这一条对 2026 年的实际开发效率有直接影响。 同一个开发者,用 AI 辅助写 Flutter 和写 UTS,产出质量和返工率不是一回事。

4.5 这一章对本项目意味着什么

生态不是"锦上添花"的加分项,它决定四件很实际的事:

  1. 遇到问题能不能自己解决 —— 引擎开源你能读能修,闭源你只能等工单。
  2. 五年后还有没有人维护 —— 8 倍的提交量差距 + 三代方案换代史,指向两种不同的平台连续性。
  3. 有没有人趟过同样规模的路 —— 90 多款线上应用、800 多名开发者的实践,意味着我们会遇到的坑大概率已经有人踩过并写下来了。
  4. AI 辅助的效率 —— 直接落在代码量最大的那两块工作上。

5 构建、发布与可扩展性

这一章是 uni-app 系限制最集中的地方,也是最容易在项目中后期才暴露出来的地方。

5.1 我们已经定下来的工程链路

  • GitLab CI/CD 流水线,带 lint、格式化、测试的卡点
  • dev / uat / prod 三套环境构建
  • iOS 由一台远程 Mac 出包,后续注册成流水线的构建节点
  • 内测分发:安卓走托管的 OTA 分发页,iOS 走 TestFlight

这套链路的核心诉求是全自动、可追溯、可复现:任何一个版本,都能从一次 git 提交自动构建出来,不依赖任何人的本机环境。

5.2 插件工具链绑定图形化 IDE

按 DCloud 官方文档原文:

"目前仅支持通过HBuilder X 创建和使用UTS插件,不支持通过cli的方式使用UTS插件"

一个绑定图形化 IDE 的插件工具链,和一条要求全自动的流水线,是结构性错配。 这不是"配置一下就好"——它意味着构建链路里存在一个必须有人打开 IDE 点按钮的环节。

普通的 uni-app x 页面本身可以自动化打包,问题集中在原生插件这一环。而由 3.2 节可知,这个项目的原生插件不是一两个,是十几个。

5.3 云端打包与离线打包:两条路各有硬约束

uni-app x 提供两种出包方式:

云端打包 离线打包
构建在哪 DCloud 的云端服务 自己的 Android Studio / Xcode
原生工程可定制范围 只能改外壳,改不了内核(见下)
能否用加密的付费插件
计费 每次 2 元;60MB 以下不额外收费,超出按档加收 免费

两种出包方式的约束对比。第二行最容易被误读,下面单独展开。

"离线打包 = 原生工程完全可控"是一个误解

离线打包确实会给你一个 Android Studio / Xcode 工程,但这个工程的核心是 DCloud 已经编译好的闭源二进制。 按官方文档,Android 侧要引入的是一组 AARlib.5plus.base-release.aaruniapp-v8-release.aarutsplugin-release.aar 等,没有源码

你能改的(外壳) 你改不了的(内核)
包名、版本号、图标、启动图 页面怎么渲染
Gradle 依赖、ABI、SDK 版本 页面容器与生命周期
AndroidManifest / Info.plist 权限项 UTS 与原生之间的通信机制
在壳外面加自己的原生模块、加 App Extension 运行时的任何行为

离线打包的可改 / 不可改边界。右列全部封装在编译好的二进制里,不提供源码,也没有修改入口。

而且连这个"外壳"本身都是被规定死的,以下两条都是官方文档原文:

  • 自定义的 Application 必须继承 DCloudApplication,新建工程默认的 MainActivity 节点必须移除 —— 换句话说,宿主工程的入口不归你,归它。你不是"把 uni-app 集成进自己的 App",是"在它的 App 里放自己的东西"。
  • 「App离线SDK不支持Kotlin」 —— 2026 年一个安卓工程不支持 Kotlin,意味着你自己要补的那部分原生代码得退回去用 Java 写。

uni-app x 用的还不是上面这套,它有独立的一套原生 SDK。按官方文档,该 SDK 当前**"仅支持VDOM模式,蒸汽(Vapor)模式的SDK还未发版"**——也就是说,走离线 / 嵌入这条路,拿不到它最新的那套渲染模式。 集成后的包体增量:iOS 约 8.7 MBAndroid(仅 arm64-v8a)约 8.1 MB。

所以准确的说法不是"离线打包可以定制",而是:你拿到的是一个必须围着闭源运行时搭起来的壳工程——能在壳外面加东西,不能改壳里面的东西。 一旦需求落在"改壳里面",这条路就是死的,且没有第二个人能帮你改,因为源码不公开。

对照 Flutter:原生侧就是一个标准的、完整的 Android / iOS 工程,ApplicationActivityAppDelegate 全部是自己的代码,Flutter 以模块形式挂进去,而不是反过来。要写 Kotlin 写 Kotlin,要写 Swift 写 Swift,没有第二套规则。

一个二选一的死结

回到上面那张表里的两个"否":

  • 官方文档明确:"uts加密插件只支持云端传统打包,不支持离线打包、也不支持安心打包"
  • 而下一节会看到,一些 App 扩展能力(如 Siri 快捷指令)官方建议的实现路径要求离线打包

推论:如果项目既用到了加密的付费插件,又需要做需要离线打包才能实现的扩展能力,这两个要求互斥,无解。 到那时的选择只剩下:放弃扩展能力,或者花钱重新买一套非加密授权(如果厂商提供的话),或者整体迁走。

另外两条商务上的绑定,也都来自官方文档:

  • 付费插件的授权绑定唯一的 appid 和包名,官方原文:「如购买者更换了这 2 个信息中的一个,需要重新购买授权」
  • 试用版只能用于自定义基座,不能用于正式发布

补充一条口径,避免夸大: 云端打包每次 2 元、最高档也就每次几十元,相对项目总投入完全可以忽略,这个数字不值得拿来做文章。 这一节的问题不是钱,是构建方式被约束住之后带来的连锁限制。

5.4 App 扩展能力的天花板

这是最容易被低估的一块。App 的形态远不止"页面 + 接口",一个用五年的 App 迟早会碰到这些需求:

  • 手机桌面小组件 / 锁屏小组件(门店当日待办、库存预警一眼可见)
  • 接入系统语音助手(Siri 快捷指令、App Intents
  • 系统级的多媒体推送、本地进度通知(比如上传进度显示在通知栏)
  • 分享扩展、通知服务扩展等各类 App Extension

对照 uni-app x 官方文档的现状:

扩展能力 uni-app x 现状
iOS 桌面小组件 没有内置 API。需在 Xcode 里用 SwiftUI + WidgetKit 做成 .appex,放进 UTS 插件的 app-ios/Plugins/,再配 nativeResources/ios/ios-extension.json 和描述文件;HBuilderX 4.61+ 的云端打包才支持携带
Siri 快捷指令 / App Intents 仅靠 UTS 插件无法实现。官方建议:离线打包的原生工程里实现 AppShortcutsProvider,再用 UTS 插件衔接业务逻辑
其它 App Extension 非内置能力,走上面同一条路径

uni-app x 的扩展能力现状,取自 DCloud 官方文档。

安卓侧同样如此:一个桌面小组件的真实交付清单

上表是 iOS 侧,容易被理解成"苹果比较特殊"。实际上安卓侧是一样的。 下面这份清单来自社区一篇 2026-05 的 UTS 插件实战教程(注明:这是社区一手实战记录,不是官方文档),做的就是一个安卓桌面待办小组件,最终要交付的东西是:

交付物 内容
三个 Kotlin 文件 TodoWidgetNative.kt(业务)、TodoWidgetProvider.ktAppWidgetProvider)、TodoListRemoteViewsService.kt(列表数据源)
AndroidManifest 注册 receiver 声明 + service 声明,service 需带 BIND_REMOTEVIEWS 权限
三个 XML 布局 小组件主布局、列表项布局、空态布局
UTS 桥接层 interface.uts + index.uts,且导出类型"必须使用 type 而非 interface"

一个安卓桌面小组件在 uni-app x 下的实际交付物。

除了这些代码本身,工具链还额外强加了三条成本,这才是关键:

  • 原文写明:「每次修改这些文件后必须重新制作自定义基座」——也就是说,改一行 XML 布局都要重新走一遍自定义基座的制作流程;只有纯 UTS / UVue 的改动才走差量编译。这在标准安卓开发里就是一次普通的增量编译。
  • 不能直接 import R取资源 ID,要用 getIdentifier() 在运行时按字符串查找——编译期的类型检查在这里失效了。
  • 出现 index.kt 找不到、R$id.class 冲突这类报错时,需要手动清掉 unpackage/cache/ 再重来。

落点:安卓侧同样要写 Kotlin、同样要碰 AndroidManifest 和 XML 布局。 而且断了之后不是回到干净的原生开发——是回到原生开发,再加上一个"每改一次就重打基座"的循环。

这里要把话说准,不能说"做不到"——做得到,但代价是三层的:

  1. 你最终仍然要打开 Xcode 写 Swift、打开 Android Studio 写 Kotlin。 "一套代码跨端"的承诺在这里就断了,而且是两端一起断。
  2. 在此之上还要额外绕一遍 DCloud 的打包体系——配 ios-extension.json、处理描述文件、每改一次原生文件重做一次自定义基座、在云端打包和离线打包之间做取舍。这是标准原生开发里不存在的额外一层。
  3. 而官方给出的那条"离线打包"退路,本身就是 5.3 里那个受限的壳工程——Application 得继承 DCloudApplication、传统离线 SDK 不支持 Kotlin、运行时闭源不可改。它不是一条干净的原生开发通道,只是一个开口更大一点的口子。

一句话概括:你既要会 Swift 和 Kotlin,又要额外学一套 DCloud 的插件与打包规则,最后还只能在别人的壳外面加东西。

相比之下,Flutter 项目的原生侧就是完整、开放、自己说了算的 Xcode 和 Android Studio 工程,做扩展就是标准的原生开发,没有第二套规则要学,也没有改不动的黑盒。

这正好回到 1.3 节那张表的最后一列:能力天花板在谁手里。

5.5 小结

工程维度 Flutter uni-app x
插件开发能否命令行化 不能,绑定 HBuilderX
接入现有 GitLab 流水线 原生支持 存在必须人工介入的环节
原生工程归谁 自己的工程Flutter 以模块挂进去 DCloud 的壳工程,自己的东西放进去;Application 须继承 DCloudApplication
运行时能否排查 / 修改 引擎开源,可读可改 闭源二进制(AAR),不可改
宿主原生代码语言 Kotlin / Swift,无限制 官方原文:「App离线SDK不支持Kotlin」
加密付费插件与离线打包 不适用 互斥
桌面小组件 / Siri 等扩展 标准原生开发 两端都要写原生Swift + Kotlin)+ 额外绕打包体系 + 每改一次原生文件重做自定义基座
构建是否经第三方云 否,全在自有流水线 云端打包方式下需要

工程链路对比。倒数第一行对有正式安全评审流程的企业是需要走流程回答的问题,不是一句"没事的"能带过的技术细节。


6 结论

6.1 成本:首版工时不会差很多

先把成本拆开,才能判断换框架到底影响哪一块:

成本构成 占比区间 uni-app x 相对 Flutter
业务逻辑与外围系统集成、联调 约 4555% 基本无差异(跟框架无关)
UI 实现 约 2025% 略省(Vue 熟悉度高)
原生能力与桥接 约 1015% 明显更贵
工程、CI、发布、可观测 约 1015% 明显更贵

首版投入的成本构成与相对差异。占比区间是基于本项目形态的估算,不同团队会有出入,但量级关系是稳定的。

        占比        uni-app x 的影响
        ────────────────────────────────
业务集成  45-55%     ─────  无差异
UI 实现   20-25%     ↓ 略省      ← 它的优势只作用在这一块
原生桥接  10-15%     ↑ 更贵      ←┐
工程 CI   10-15%     ↑ 更贵      ←┘ 它的额外成本作用在这两块

uni-app x 的效率优势作用在占比第二小的那一块,而它的额外成本作用在另外两块。 一加一减,首版总投入差异在 ±10% 以内,可以认为基本持平。

这句话给得干脆,不留模糊:成本不是选择 Flutter 的理由,也不是选择 uni-app x 的理由。

6.2 五年视角:这才是真正的差异

首版持平,但这个系统要跑五年,需求只会越加越多。那就把时间轴拉长,两边各回看五年。

Flutter 这五年(2020 → 2026):

从一个不被看好的新框架,长成跨端开发的主流选择。今天主仓库 178,643 star、31,002 fork、91,171 次提交,引擎到框架全部开源。同时它支持以模块形式嵌入已有的原生 App,意味着它既能做整个 App,也能作为某条业务流嵌进别人的 App 里——这是一条向上兼容、路越走越宽的路线。

需要说明的是,原生开发并没有消失,平台特性、系统扩展这些活仍然要写原生——而这恰恰和本项目的情况吻合:我们本来就要写十几个原生插件。

DCloud 这五年:

同一时期换了三代 App 方案——5+ 应用、nvue(基于修改过的 Apache Weex 引擎,而 Weex 本身已于 2021 年 5 月从 Apache 孵化器退役、6 月仓库归档),到现在的 uni-app x。官方已说明 nvue 和 5+ 的维护在 2024 年停止,建议迁移到 uni-app x。

这不是攻击,这是可查证的平台连续性记录。 一边是同一条主线持续演进十一年、没让用户推倒重来过;一边是每隔几年换一代底座、并要求存量项目迁移。站在 2026 年选一个要用到 2031 年的技术栈,这条记录应该被正面评估。

6.3 厂商投入与治理结构

Flutter uni-app x
主导方 Google + 全球开源社区 DCloud 一家公司
可见的工程投入 91,171 次公开提交,含引擎 11,216 次公开提交,Runtime/SDK 闭源无公开记录
极端情况下的退路 BSD 开源,可自行 fork 维护 没有第二个可以接手的主体

治理结构对比。这是风险管理问题,不是产品好恶问题。

6.4 推荐 Flutter

四条理由收口:

① 架构路线就决定了适用性。 uni-app 系是为"小程序 + H5 + App 多端复用"设计的,而这个项目正在关掉那六套小程序、首版只发两个平台。它最值钱的能力在这里没有买家,我们只承担代价。

② 本项目原生能力密度高,这部分工作量不会因换框架而减少。 十几项原生能力要逐个实现、逐个在两端验证。Flutter 在原生桥接、指定 SDK 接入、以及与既有流水线的契合度上都更成熟,而 uni-app x 的效率优势只作用在占比约两成的 UI 实现上。

③ 生态与开放程度不在一个量级。 8 倍的公开提交量差距,加上"Flutter 引擎开源、uni-app x Runtime 闭源"这个层次差异——决定了遇到底层问题时,一边能自己解决,一边只能等厂商。

④ 能力天花板归属不同。 Flutter 的天花板是我们自己的工程能力;uni-app x 的天花板是厂商插件市场和打包体系。五年周期里,这一条的复利效应最大。

6.5 公平地说,uni-app x 强于 Flutter 的三点

这一节不能省。一份只说对方缺点的评估,在技术评审面前站不住。

① 鸿蒙支持目前确实更完整。这一条要说得精确,分三层:

  • 对 uni-app x 有利的部分,如实写明: UTS 可直接编译成鸿蒙的 ArkTS,鸿蒙在它这里是一等公民路径。而 Google 已经明确不会在 Flutter 主线支持鸿蒙——官方仓库里那条鸿蒙适配 issue(#150536)的处理结果是 Closed as not planned。这不是"还没做",是"不打算做"。
  • 但差距在收窄: 鸿蒙侧的 Flutter 适配由 OpenHarmony-SIG 的社区分支承接,2026 年 1 月已成立 Flutter SIG 做治理,按季度跟进主线版本;目前 3.41 的鸿蒙版已发布,3.44 的鸿蒙版预计 2026 年 9 月。它不是一个无人维护的野生 fork。
  • 对本项目的具体含义: 我们的版本基线正是 Flutter 3.44.9,对应的鸿蒙版下个月就到。鸿蒙不在本项目首版范围内,而我们刻意停在 3.44.9 没追最新版,本来就是为后续接鸿蒙留兼容窗口。所以这条差距在本项目的时间线内是可控的。

结论仍然是:如果鸿蒙将来变成硬需求,uni-app x 在这一项上更省事,应当如实计入。 只是它比"Flutter 做不了鸿蒙"要小得多。

② 小程序与 H5 的复用能力是真实存在的。 将来若又有"同一套业务同时发 App 和小程序"的需求,它的价值会立刻显现。本项目用不上,但这是它客观的长处。

③ UTS 这门语言的设计思路是对的。 它直接编译成 Kotlin 和 Swift,比传统那种"传一个字符串方法名 + 一包弱类型参数"的桥接方式干净得多,方向上是正确的。我们对 uni-app x 的保留意见不在语言设计,在它外面那层工具链和打包体系——第 4、5 章列的问题,没有一条是 UTS 语言本身造成的。

以上三点是能力层面的长处。另外还有三项 uni-app x 占优、但不属于能力范畴的:包体更小、内存占用更低、支持热更新——这三项连同 DCloud 官方对比材料的逐条核验一并放在附录 C

6.6 如果最终选择 uni-app x,需要先落实的六项前提

如果业务方权衡后仍倾向 uni-app x,以下六项应在开工前落实——它们会让这个选择的真实成本变得可见:

  1. F6 书面同意在其页面中引入 uni.webview.js,并承诺配合联调排期。
  2. 神策提供与我方后端版本匹配的 uni-app x SDK,并明确后续支持与升级责任。
  3. Bugly 的 UTS 封装完成并验证,含 iOS 侧的崩溃符号化。
  4. DCloud 明确 CLI / CI 的可行路径;如果没有,我方需接受构建链路中存在人工用 HBuilderX 出包的环节,并据此调整发布流程。
  5. 确认云端打包与离线打包的取舍:是否会用加密付费插件,是否有需要离线打包的扩展需求,两者互斥时以哪个为准。并明确知悉:即使走离线打包,原生工程仍是围着 DCloud 闭源二进制的壳工程,运行时行为不可改。
  6. 接受首版拿不到多端复用收益——那六个小程序正在被这个项目关掉。

前四项任何一项落不实,都应重新评估选型。

6.7 最终结论

综合本项目的实际约束——架构路线的适配性、F6 集成、原生能力密度、指定的两个 SDK、既有的工程流水线、生态开放程度、以及五年周期内的能力天花板——

我们推荐 Flutter。


附录 A 数据与事实来源

本文档中所有关于 uni-app / uni-app x 的技术判断,除单独标注者外,均来自 DCloud 官方文档或对应厂商官方文档;社区数据取自 GitHub 公开接口。全文只有一处引用社区来源(5.4 节的安卓小组件交付清单),已在正文和下表中明确标注。便于客户方自行复核。核验日期:2026-08-25

结论 来源
主仓库 star / fork / 提交数等社区数据 GitHub REST APIflutter/flutterdcloudio/uni-app
网页向 App 发消息需引入 uni.webview.1.5.5.jsApp 向网页走 evalJS() uni-app x — web-view 组件
UTS 插件只支持通过 HBuilderX 创建和使用,不支持 CLI uni-app x — UTS 插件
付费插件授权绑定 appid + 包名;加密 UTS 插件只支持云端打包 uni-app x — 插件发布与授权
iOS 小组件需 Xcode 做 .appex + UTS 插件携带 + ios-extension.json uni-app x — UTS 插件(iOS Extension 章节)
Siri 快捷指令仅靠 UTS 插件无法实现,需离线打包 + AppShortcutsProvider uni-app x — UTS for iOS
云端打包与离线打包的能力差异 uni-app x — 云打包
离线 SDK 以编译好的 AAR 交付(lib.5plus.base-release.aaruniapp-v8-release.aarutsplugin-release.aar 等,不含源码);自定义 Application 须继承 DCloudApplication、默认 MainActivity 须移除;「App离线SDK不支持Kotlin」 DCloud — App 离线打包(Android
uni-app x 有独立的原生 SDK(分 Android / iOS / 鸿蒙版);"仅支持VDOM模式,蒸汽(Vapor)模式的SDK还未发版";包体增量 iOS 约 8.7 MB、Android arm64-v8a 约 8.1 MB uni-app x — 原生 SDK / 渐进式集成
云打包计费:每次 2 元;60MB 以下免费,超出按档加收 uni-app — 云端打包
uni-app x 组件与 API 大部分 Apache-2.0 开源;Runtime / SDK 知识产权归 DCloud uni-app x 是什么uni-app 使用许可协议
uni-app x 不支持传统 uni-app 的原生插件;旧插件停止新增上架 uni-app x 是什么
nvue 基于修改过的 Weex 渲染引擎 uni-app — nvue 介绍
nvue 与 5+ 的官方维护于 2024 年停止,建议迁移 uni-app x uni-app x 是什么
Apache Weex 于 2021-05-14 从孵化器退役,仓库 2021-06-03 归档 Apache Incubator — Weex 状态页apache/incubator-weex
神策 uni-app x SDK 不在插件市场,需联系技术顾问索取 神策分析 — uni-app x 集成文档
Flutter 官方 agent skills 与 MCP server Flutter — Agent skillsDart and Flutter MCP server
Flutter Skills 发布公告(2026-05-06 Introducing Skills for Dart and Flutter
DCloud 官方的 uni-app x 与 Flutter 对比(包体 18M / 8.5M、内存约 138MB / 103MB、仅覆盖 VDOM 模式、"需求墙尚有未完成项"等自陈边界) uni-app x — 跨平台技术选型
字节跳动 90+ 款 Flutter 应用、800+ Flutter 开发者、产品清单与"节省约 1/3 开发时间"(口径为对比原生双端) Flutter 中文文档 — 开发者故事 / 案例2026-06-22 更新)
安卓桌面小组件在 uni-app x 下的交付清单:3 个 Kotlin 文件 + Manifest 注册 + 3 个 XML 布局 + UTS 桥接;「每次修改这些文件后必须重新制作自定义基座」;需用 getIdentifier() 取资源 ID (社区来源,非官方文档) 掘金社区 UTS 插件桌面小组件实战教程,2026-05-31
Google 明确不在 Flutter 主线支持鸿蒙(Closed as not planned);鸿蒙适配由 OpenHarmony-SIG 社区分支承接,2026-01 成立 Flutter SIG3.41 鸿蒙版已发布、3.44 鸿蒙版预计 2026-09 flutter/flutter issue #150536OpenHarmony-SIG / flutter_flutter

外部来源清单。凡本文档中标注为"推论"的内容(如"F6 需要改造页面"、"加密插件与离线打包互斥"),均由上表中的事实推出,推理过程已在正文中写明。


附录 B 术语表

给非技术读者:

术语 通俗解释
原生(Native 用 Android 和 iOS 各自官方的语言和工具开发,是"最正统"的做法
WebView 系统内置的浏览器组件。App 里嵌一个网页,就是靠它
JSBridge App 和它内嵌的网页之间的通话线路。网页想调手机的相机,得通过它
自绘引擎 不用系统自带的按钮和列表,自己从零画出每一个像素。Flutter 用的就是这个
Runtime(运行时) App 跑起来时在底下支撑它的那层引擎代码。它闭源,就意味着出了问题只能等厂商
UTS uni-app x 的编程语言,能编译成安卓的 Kotlin 和苹果的 Swift
UVue uni-app x 的页面写法,基于 Vue
nvue / 5+ DCloud 上两代的 App 方案,官方维护已于 2024 年停止
Weex 阿里开源的跨端方案,nvue 的渲染引擎基础,已于 2021 年从 Apache 退役
Dart Flutter 的编程语言
Pigeon Flutter 官方工具。写一份接口定义,自动生成三种语言的对接代码,避免手写出错
HBuilderX DCloud 出品的开发工具(IDE),uni-app 系的插件开发目前离不开它
CLI(命令行) 不用打开图形界面,用命令直接执行。自动化流水线依赖这个
CI/CD(流水线) 代码提交后自动检查、自动构建、自动发布的机制
云端打包 / 离线打包 前者把构建交给厂商的服务器;后者在自己的电脑上构建,但拿到的工程核心仍是厂商编译好的二进制
AAR 安卓的二进制打包格式。拿到 AAR 只能调用它,看不到也改不了里面的代码
App Extension(扩展) App 主体之外的附加组件,比如桌面小组件、分享面板、语音助手指令
符号化 崩溃报告里原本是一串看不懂的地址,还原成"哪个文件哪一行出错"的过程
热更新 不经应用商店审核,直接把新版代码下发到用户手机上
VDOM / 蒸汽(Vapor)模式 uni-app x 的两种渲染模式。后者更新,性能更好,但配套的原生 SDK 尚未发版
MCP 一种标准协议,让 AI 编程助手能读懂某个框架的专有知识
Agent Skills 打包好的一组指令,教 AI 编程助手按某个框架的最佳实践干活

术语对照表。


附录 C 对 DCloud 官方对比材料的核验

DCloud 官方文档里有一页专门做 uni-app x 与 Flutter 的对比(「跨平台技术选型」)。客户方技术人员检索"uni-app x vs Flutter"时大概率会看到这一页,所以我们把它读完并逐条核验了。 结果如下——凡属实的直接认,凡没有数据支撑的说明它没有数据支撑,不做反向解读。

对比页的论点 核验结果 对本项目的意义
Flutter 安装包更大(实测 18M 对 8.5M 属实。 自绘引擎必须打进包里,这是路线本身的代价 差约 10MB。门店内部业务 App,企业分发、无包体 KPI,不构成决策变量。且 uni-app x 走离线 / 嵌入路径同样有增量:iOS 约 8.7 MB、Android arm64-v8a 约 8.1 MBDCloud 官方数字)
Flutter 内存占用更高(实测 约 138MB 对 103MB 属实 差约 35MB。门店配发的作业终端,现代机型上不产生可感知影响
「dart与原生API的通信…通信损耗非常明显」 未附实测数据与测试条件,属定性表述 本项目的原生调用(扫码、拍照、上传)是低频、事件驱动的,不在渲染热路径;且接口由 Pigeon 生成三端强类型代码,不是字符串方法名。本项目真正吃紧的通信链路是嵌 F6 那条——恰恰是 uni-app x 更弱的地方,见 3.1
「原生渲染和flutter自渲染并存时,问题很多」 未附实测数据,但原生与自绘混排确是业界已知难点,这个方向上的提醒是成立的 本项目唯一的混排点是 WebView,用的是 Flutter 官方团队维护的一等公民插件,不是第三方封装。混排面积小且可控
「dart生态…以及比较难用的嵌套写法」 生态一项与第 4 章的公开数据相反(公开提交量、大厂落地规模均为 Flutter 占优);嵌套写法这条是真实体验问题,深层嵌套的可读性确实不如模板语法 嵌套写法属编码习惯与工具问题:IDE 的结构提示、格式化与重构快捷键已覆盖,团队上手一两周即适应。这一条我们不辩解,但它不影响能力上限
「热更新」 属实,且是对方一条真优势 单独说明,见下

对 DCloud 官方对比页各项论点的核验。

这份对比里给出实测数字的只有包体和内存两项,差距分别约 10MB 和 35MB;其余论点均为定性表述,未附测试条件或数据。

我们认为这个事实本身值得客户方注意:一家厂商在自己撰写的公开对比材料里,通常会把手上最有力的证据放上来——而这份材料里最有力的证据是安装包大小。 这从侧面说明了两条路线的差距集中在哪些维度上:不在能力,在体积。

同一页里,DCloud 也标注了这份对比的边界。我们认为这些自陈是客观的,一并列出:

  • 该测试仅覆盖 VDOM 模式,蒸汽(Vapor)模式不在对比范围内
  • 官方原文提到其**「需求墙尚有未完成项」**
  • Android 侧页面元素过多时仍会拖慢性能,复杂场景需改用 draw 方式实现
  • 引入常用库之后,uni-app x 的包体同样会增长

这几条说明上面那两个数字是有前提的:它们是特定模式、特定测试工程下的结果,不宜直接外推到一个有十几项原生能力、要嵌第三方网页的真实业务 App 上。

补充一条对方的真实优势:热更新

uni-app 支持热更新(wgt 方式),Flutter 不支持。这一条我们主动列出,不等对方提。

对很多项目来说这是实打实的价值——线上出了问题不用等应用商店审核,直接下发修复。需要一并说明的是:

  • 苹果的审核政策对"绕过商店下发可执行逻辑"长期处于灰色地带,规模化使用存在被下架的风险敞口
  • 本项目的发版链路已经定了:安卓走托管的 OTA 分发页,iOS 走 TestFlight + App Store,都是正规链路
  • 企业侧的安全与合规评审,通常也不倾向于接受"可以绕开商店直接下发代码"这种能力

所以准确的说法是:这条优势客观存在,但在本项目已确定的发版模式下用不上。 如果将来发版策略改变、热更新变成硬需求,这一条应当重新计入。

这一节的用途

写这一节不是为了驳倒谁,是为了让评审会上不出现"我在网上看到 DCloud 说 Flutter 怎样怎样"这种悬空的讨论。对方的每一条论点,上面都有一个明确的答复:属实的认下来并说明影响,没有数据的指出它没有数据,对我们不利的(包体、内存、热更新、鸿蒙)主动列出。

结论不因此改变——这些差异全部落在本项目不敏感的维度上,而第 3 章那几条落在敏感维度上的差异,方向是相反的。