AI 时代,我为什么推荐用 cj-tauri 开发桌面应用

11 阅读1分钟

AI 时代,我为什么推荐用 cj-tauri 开发桌面应用

先说一件更基础的事:我们写代码的方式变了。

两年前写一个桌面工具,节奏是「我敲、我调、我试」。现在是「我描述、AI 落笔、编译器裁决」——我给出意图,AI 给出几百行,然后真正的裁判不是 AI 的自我总结,而是编译器那句 error:。

这个转变把三个原本次要的成本顶到了台前:编译要等多久、构建目录吐多少垃圾、产物交付给别人有多大。以前一天编十次,慢一点无所谓;现在 AI 一轮改完就想立刻跑起来看,编译慢就从「可以忍」变成「打断工作流」。以前 target/ 涨到几个 G 反正只有我自己看;现在要给同事、给用户、给一台干净的机器甩一个能双击就跑的文件。

cj-tauri 就是我在这个背景下用来写桌面应用的东西。它不是玩具:30 多个可运行的示例、101 个仓颉源文件两万五千多行、351 个单元测试、Windows/Linux/鸿蒙三端有真机取证。下面把我选择它的理由、以及它的真实代价,一条条摊开讲,数字都给来源,方便你复核。

Tauri 与 cj-tauri 的对照


一、先说清 cj-tauri 是什么

一句话:它是「仓颉版 Tauri」——后端用仓颉静态编译成原生二进制,前端是你熟悉的 Web 技术,界面跑在系统 WebView 里。

这个定位决定了它的形状:

  • 不带 Chromium、不带 Node。界面用系统自带的 WebView(Windows 是 WebView2、Linux 是 WebKitGTK、鸿蒙是 ArkWeb),你的产物里没有第二个浏览器内核。
  • 前端随便用什么。create 缺省给一个零 Node 的内联 HTML 模板,也支持 Vue 3 / React 18 模板走 Vite。
  • 命令面照着 Tauri 抄。npx cj-tauri create 建工程,cj-tauri dev 起开发服务器,cj-tauri build 出产物。从 Tauri 过来的人几乎不用重学脚手架。
  • 一份后端代码多端跑。平台差异只允许出现在两处:仓颉侧 @When 条件编译,和 C 桥 native/platforms/*/。

cj-tauri 分层架构

它想解决的问题很朴素:桌面应用最贵的那部分从来不是业务代码,而是「把业务代码变成用户能双击的东西」这一路的基础设施。这条路 Tauri 用 Rust 走通过一次,cj-tauri 想用仓颉再走一次——而且是能同时走到鸿蒙的那一次。


二、第一个理由:产物是真的小,而且「小」能复核

「小」这个字在宣传语里不值钱,值钱的是它能被一条条复核。

我刚在本机重新量了一遍(2026-11-08):

产物(Windows 单文件 exe)体积
serial-waveform.exe4.89 MB
markdown-notes.exe5.20 MB
cj-link.exe5.90 MB
modbus-poll.exe5.97 MB
typing-poem.exe6.02 MB
movie.exe10.04 MB
music.exe10.21 MB
leetcode-gui.exe10.43 MB

轻量工具落在 4.7~6MB,带 HTTPS 和较多资源的示例在 10MB 上下。

这里我要主动补一句反例,避免你按「都很小」预期:同一批产物里还有两个重度示例——内嵌了 AI agent 的 ai-chat.exe 是 26.75MB,内嵌完整编辑器的 cjnote.exe 是 34.35MB。它们大是因为真的带了东西(页面资源、内嵌二进制),不是因为框架本身肥。框架加一个空窗口的基线,就是上表那 4~6MB 的量级。

各示例产物体积对比

体积只是表象,真正决定「能不能甩给别人」的是依赖表。仓库里有实测记录(2026-10-13,八份产物逐个 objdump 核过):

  • 八份产物导入的 DLL 名字加起来只有 9 个,全是 Windows 系统自带的:KERNEL32 / USER32 / SHELL32 / ole32 / msvcrt / WS2_32 / comdlg32 / dbghelp,走 HTTPS 的再多一个 CRYPT32(读系统证书库)。
  • 第三方运行时 DLL 一个都没有:msvcp* / vcruntime* / libgcc* / libwinpthread* 全为零,也没有任何 Node 相关的东西。
  • 子系统是 Windows GUI——双击不会先弹一个黑窗口。

这三条合起来才是「免安装」的完整含义:在一台从没装过仓颉 SDK、也没装过 VC++ 运行库的 Windows 上,双击就能开窗。仓颉运行时的 TLS 加载器那类按名字动态加载的 DLL 是边界情况,仓库里如实写了「未验证前不下结论」,我也不在这里替它吹。

对 AI 协作来说,这件事的意义比「省硬盘」更实在:你交付出去的是一份可审计的产物,而不是一棵几百个包的依赖树。出问题时排查范围是你自己写的两万行,不是三十万行第三方代码。


三、第二个理由:编译等待,短到不会打断 AI 节奏

这是我认为在 AI 时代最被低估的一条。仓库里的实测表(同一台机器、同一份脚本):

项目实测
最小示例 examples/hello 全量冷编译(静态链入框架)50 秒
同一示例改一行再编(增量)25 秒
构建目录 target/(该示例 / 框架本身)6.7M / 42M
产物 main(静态链接)4.5M
独立小程序(leetcode 判题器,静态链接 + strip)冷编译 0.4~1 秒,产物 2.7M

翻译成日常感受:全量几十秒,增量二十几秒,写小工具的编译快到感觉不到(0.4 秒那种,基本等于「按下按钮就出结果」)。构建垃圾是几十兆级,不是几个 G 级——我现在的框架 target/ 目录就是实打实的 42M。

这直接改变了 AI 协作的闭环速度。AI 一次改动之后,我要的是立刻看到它能不能跑,而不是去泡杯咖啡回来发现编译报错在第一行。反馈周期从分钟级压到秒级,AI 那种「一次改一大片」的用法才真正成立——改错的面大没关系,只要代价低到可以立刻重来。

不过因果要说清楚,这条最容易被误读:

仓颉这边快,一部分是因为项目本身瘦(依赖少、代码短,没有一排第三方 crate 要先编一遍),加上工具链轻。 不是编译器比 rustc 更聪明。Rust 的慢换来的是极致优化和一个巨大到不用自己造轮子的生态。

这笔账怎么算,取决于你在写什么——我不想用它去踩 Rust,只想说清楚「轻量工具、快速迭代」这个场景里,等待时间的差距是真实收益。


四、那 Rust / Tauri 呢:它的代价也是具体的

既然要讲清楚为什么推荐,就得讲清楚我在拿什么做对照。

Rust 是「编译期安全」这条路上最有说服力的答案,Rust + Tauri 也是当下桌面混合开发最成熟的组合。我不否认这些。我想说的只是:它被吐槽最多的两条,恰好是日常最磨人的成本——编译慢、构建目录吐垃圾。

  • 依赖一多,泛型单态化 + 过程宏展开一起来,target/ 动辄几百 MB 到几 GB(debug 和 release 还各留一份);
  • 改一行等半分钟是常态,项目大一点、机器差一点,一分钟往上很常见;
  • 生态太大也有代价:一个不起眼的工具链,Cargo.lock 里能拽进来上百个包,供应链审计、版本冲突、交叉编译踩坑都从这里来。

这里我必须把方法论摆出来:我这台机器上没装 cargo,所以不做同机、同项目的对照实验,上面这些是业界公认的现象,不是一个我亲手跑出来的数字。而仓颉侧的数字(50 秒 / 25 秒 / 42M)是仓库里脚本可复算的。

拿「我这边的实测」对「对面公认的口碑」是不严谨的对照,所以我把它写成这样:你可以按自己的项目比例去感受,而不是假装我有两组同口径数据。这条线我觉得比多一个漂亮数字重要——毕竟选型错了,是你后面一两年陪着它。


五、第三个理由:AI 写代码时,编译器是最好的审稿人

这一段是我认为 cj-tauri 在「AI 时代」这个题目下最硬的理由,而且它和框不框架无关,是语言层面的。

① 静态类型 + 编译期检查 = 给 AI 的幻觉设了一个落点。

动态语言里 AI 编出来的 API 名字错了,要真跑到那一行才炸;静态编译的语言是编译期就过不去。仓颉属于后者。这套工作流的价值在项目变大时才显出来:本仓 101 个仓颉源文件、25,431 行代码、351 个 @Test——编译器的报错比 AI 的自述可信。它说「改好了」,编译器说「第 340 行类型不匹配」,后者是唯一可以据以行动的信号。

② 语法简单,代码短,AI 一次能改对的面就大。

类型推断、模式匹配、lambda、字符串插值都有,一个命令处理器六行、一个能跑的窗口应用十来行。同一件事用的代码越少,AI 一次改对的概率越高,人 review 的面也越小。FFI 也不隆重——一行 foreign func 直接调系统库,中间没有多余的包装层(本仓的 SQLite 插件就是直接调系统 libsqlite3)。

③ @When 条件编译让「一份代码多端」对 AI 也友好。

不用为每个平台记一套 API:AI 只要在同一个函数里按平台门禁写分支,剩下交给编译器。这比让 AI 记住「Windows 上要这样、鸿蒙上要那样」的三套代码可靠得多。

④ 它多给了一样 Rust 给不了的东西:鸿蒙。

后端逻辑与鸿蒙原生同源,桌面和鸿蒙共用一套业务代码。这在别家语言上没有现成路径。如果你的目标里有鸿蒙 PC,这条几乎是一票否决级别的差异。


六、生态已经不是「一个玩具示例」了

这是我觉得最需要摆事实的一条,因为「新框架」三个字天然让人怀疑能不能用。

我数了下仓库现在有 32 个示例与模板目录,其中大部分是真能跑的工具,不是 hello world:

示例一句话
modbus-pollModbus TCP/RTU 调试工具:多面板并行监控、FC 01-04/05/06/15/16、报文监视、CSV 记录
mqtt-clientMQTT 调试台:协议由插件纯仓颉实现(没用现成库),自带 mock broker,E2E 27 条断言
redis-clientRedis 调试台:SCAN 游标分页 + MATCH + TYPE 过滤、发布订阅,RESP2 双 socket 自研,47 条断言
sqlite-browserSQLite 浏览器:仓颉 FFI 直连系统 libsqlite3,不经 C 桥
http-clientHTTP API 客户端:页面零 fetch,请求全由仓颉侧直发,TLS 走系统证书库、不关校验,55 条断言
cj-link串口/网络二合一调试助手:串口 + TCP + UDP 共用收发日志,HEX/ASCII、CRC、定时发送
cjnoteMarkdown 笔记 + 大纲 + 菜单,真实日用级应用

示例:Markdown 笔记应用

示例:HTTP API 客户端

配套的还有一套插件体系(fs / shell / serial / dialog / async 等,命令自动登记成 插件名:短名)、三套脚手架模板,以及一份和 Tauri 的逐条概念映射表——#[tauri::command] 对应什么、Capabilities 对应什么、fs:scope 对应什么,迁移时照着改就行。


七、它现在的代价,我也照实说

一个只讲优点的推荐没有价值。以下是我在用、或者明确已知的短板:

① 库生态远小于 crates.io。 很多轮子得自己造——本仓的 MQTT、Redis RESP2 都是纯仓颉手写的。好处是零第三方依赖、可审计;代价是你得自己写。如果你要的是「现成的海量第三方库」,先去 Rust,这句话我是认真的。

② 工具链还在快速演进。 版本配对的坑真实存在(cjc 与 opt 差一代会崩、cjpm 的增量缓存偶尔会跳过链接),所以本仓的验收判定统一成「看产物」而不是「看 build success」。这不是洁癖,是被坑出来的纪律。

③ 平台覆盖有缺口。 Windows / Linux / 鸿蒙(真机闭环)可用,macOS 未做。移动端也没有。

④ 能力矩阵不是满的。 托盘、全局快捷键、文件拖入、原生对话框、系统通知在 Windows/Linux 落地(部分为桩),鸿蒙侧多数能力位为 0 但会如实拒绝而不是假装成功;自动更新(updater)暂无对应物;shell 子进程是同步阻塞、没有流式输出,长驻进程不适用。

⑤ 鸿蒙侧有形状差异。 菜单只支持扁平、无禁用位,嵌套树写法要退化;串口这类能力受系统签名与权限门槛限制。

⑥ Tauri 的习惯要改。 命令三处联动缺一不可(实现 + 注册 + 清单放行),少一处报 command not registered / command not allowed;权限集和 scope 都是「声明 ≠ 放行」,比 Tauri 的 ACL 更显式,也更容易漏。排查第一件事是看桥日志。


八、所以,什么时候该选它

把上面的东西压缩成一张判断表:

你的情况建议
写内部工具、调试台、小桌面应用,要快速迭代很合适。编译秒级,产物 5MB,甩一个 exe 就交付
用 AI 辅助开发,希望编译期就能拦住错误很合适。静态类型 + 351 个测试,编译器当审稿人
目标平台包含鸿蒙 PC优先考虑。桌面与鸿蒙同源,这是它独有的路径
交付形态是「给非开发者的免安装单文件」合适。零第三方 DLL、GUI 子系统、双击即开
重度依赖第三方生态(拿现成 crate 拼装)先去 Rust/Tauri。仓颉生态还小,自己造轮子的成本要算进去
必须支持 macOS / iOS / Android暂不适用。这几个平台尚未落地

一句话总结:如果你要的是「AI 帮你写 + 编译器把关 + 一条命令出小产物」这套工作流,cj-tauri 很合适;如果你要的是现成的海量第三方库,先去 Rust。 Rust 证明的方向是对的,仓颉是同一方向上的另一个答案。


九、想试试的话,从这三步开始

# 1. 建工程(CLI 是 npm 包,这一步需要 Node)
npx cj-tauri create my-app

# 2. 开发:起 dev server 并开窗(Vite 由 CLI 托管)
cd my-app && cj-tauri dev

# 3. 出产物
cj-tauri build

一个能跑的最小窗口应用大概十来行仓颉——前端是普通 HTML,后端注册一个命令处理器,桥接由框架管好。上手门槛基本等于「会写网页 + 会写一个函数」。

如果你从 Tauri 过来,直接看仓库里的《与 Tauri 的差异清单》:概念映射、行为差异、平台能力差异、迁移清单四节,照着改,一两个小时能把一个小项目挪过来。


结语

我不觉得 cj-tauri 现在就该取代谁。它还很年轻,生态、平台覆盖、工具链成熟度都有明显缺口,我在上面也一条条写了。

但它代表的那个方向我觉得是对的:在 AI 参与写代码之后,桌面开发的竞争点从「功能能不能实现」前移到了「改一次要等多久、交付出去多大、出错时谁替你兜住」。前两件事是工程成本,第三件事是正确性——而静态编译的语言恰好在这三件事上同时给分。

这就是我在 AI 时代推荐它的原因:不是因为它比谁强,而是因为它把这三件事的成本都压得很低,并且允许我用一句话描述、让 AI 落笔、由编译器裁决、由自检收口。

Rust 走的也是这条路。多一个同方向的答案,对写代码的人是好事。