跨平台桌面便签开发实录:从Electron到Tauri的技术选型与踩坑指南
2026/9/13 17:39:56 网站建设 项目流程

跨平台桌面便签看起来是个小品类,但真做起来,复杂的程度远超预期。吐司便签(Toast Notes)是我花了几个月业余时间从零写的一款跨平台桌面便签待办应用,目标只有一个:在 Windows、macOS、Linux 上都能做到“双击就记、随手置顶、到期提醒”。如果你也在考虑做一个常驻系统托盘的桌面小工具,或者正在纠结便签类应用的技术选型,这篇从动机、选型、实现到踩坑的记录,应该能帮你少走不少弯路。

1. 从屏幕便利贴到自研应用:这个项目到底想解决什么

1.1 市面上不缺便签工具,缺的是“刚刚好”的那个

我大概属于那种桌面重度用户:写代码要开一堆参考资料,做方案要来回对需求,临时电话里记个取件码、车牌号,都是家常便饭。以前我的习惯是打开系统自带的便签,Windows 用桌面的便笺,macOS 用 Stickies,用着用着就发现问题了——换台电脑,便签没了。

后来我也用过各类云笔记和在线文档,笔记确实是云同步了,但问题也来了:工具太重。开一个在线文档要等半天,记录一个“楼下快递柜取件码 8-3-502”这种几秒钟的事情,根本不值得启动一个几百兆的编辑器。专业待办应用我也试过,功能确实强大,但需要建项目、分标签、设优先级,配置本身变成了一种负担。对于一个便签来说,这套仪式感太重了。

我需要的功能其实很朴素:双击就能记,窗口永远贴在桌面某个角落,颜色能够区分“紧急”“待办”“随手记”,到了时间能弹个提醒。这样的工具在各平台上其实都有,但很少有项目愿意把这几个需求同时做透。既然找不到“刚刚好”的那一个,我决定自己做。

1.2 “吐司”这个名字,以及三个坚持的产品原则

项目叫 Toast Notes,中文名叫吐司便签。名字有两层意思:一是 toast 在系统通知里的意思是“轻提示”,和便签的定位吻合;二是烤面包机把吐司弹出来的动作很利落,我希望这个应用给人的感觉也是这样——轻快、不占资源、不打扰人。

定了名字之后,我给产品立了三条原则,后面所有功能决策都围绕它们展开:

  • 启动快:不能在用户想记东西的时候还等它加载。
  • 不打扰:默认不弹窗不推送,提醒只在该提醒的时候出现。
  • 数据不绑架:笔记数据得是用户自己能拿到的普通格式,不能绝版在私有协议里。

这三点直接影响了后续的技术选型和存储方案。比如“启动快”这一条,就让我第一个否掉了 Electron 路线,原因后面章节详说。

2. 技术选型:为什么在 2024 年我仍然放弃了 Electron

2.1 三条主流跨平台路线的横向对比

动手之前,我在 Electron、Tauri、Qt 三条路线上纠结了很久。这里先按我的实测感受列一个对比,数据以普通便签类工具的真实运行情况为参考,不同业务场景会有差异。

对比维度ElectronTauri 2.xQt(QML)
安装包体积通常 60MB 起优化后 5-10MB打包后 30MB 左右
空闲内存占用150-300MB30-60MB20-50MB
UI 开发效率高,Web 技术栈高,Web 技术栈中等,需学 QML
系统托盘/全局快捷键成熟但偏重官方插件完善原生支持
后端能力Node.jsRustC++
分发自更新electron-builder 成熟内置 bundler,多平台支持原生打包工具链复杂

可以看到,Electron 在生态上依然是最成熟的,但它的内存占用对一个常驻系统托盘的小工具来说确实是硬伤。便签应用不是打开用一下就关,它是开机自启、一直挂在后台的。如果它吃掉 200MB 内存,用户第一反应不是“这个便签好用”,而是“这玩意怎么这么卡”。

2.2 最终选择 Tauri 2.x 的三个决定性理由

选 Tauri 2.x 有三个决定性理由。

第一,便签是典型的常驻型应用,资源占用就是用户体验本身。Tauri 直接调用系统 WebView,没有自带 Chromium 的后台开销,空闲内存能压到 50MB 左右,这对后台工具类应用是质变。

第二,Tauri 2.x 的插件体系比 1.x 完善了太多。系统托盘、通知、全局快捷键、SQLite 都有了官方插件,窗口 API 也补齐了透明、置顶、跳过任务栏这些能力。很多在 1.x 里需要自己写 Rust 绑定的功能,2.x 里直接有现成接口。

第三,Rust 后端做文件操作和定时任务非常稳。便签要频繁读写数据、定时扫描提醒、处理窗口状态,Rust 的线程模型和错误处理让这些逻辑出问题的概率远低于我用 Node.js 写后端时的心理预期。

2.3 项目骨架与数据流向

最终的技术栈是 Tauri 2.x + React + TypeScript,前端负责便签的渲染和交互,Rust 负责窗口控制、文件读写和提醒调度。项目结构大概是这样的:

toast-notes/ ├── src-tauri/ │ ├── src/ │ │ ├── main.rs │ │ └── commands.rs │ ├── capabilities/ │ ├── tauri.conf.json │ └── icons/ ├── src/ │ ├── components/ │ │ ├── NoteCard.tsx │ │ ├── TodoItem.tsx │ │ ├── TagView.tsx │ │ └── TrayMenu.tsx │ ├── stores/ │ ├── lib/ │ │ ├── storage.ts │ │ └── reminder.ts │ └── main.tsx └── package.json

数据流向很直接:前端通过 Tauri 的invoke调用 Rust 命令,Rust 命令操作 SQLite 数据库和本地文件。整个链路短,出了问题也容易定位。这里要多说一句选型心得:可以多花点时间在技术选型上,但别在选型上无限内耗。当初我也花了两周反复对比,后来发现真正重要的是赶紧把第一个可运行 Demo 跑起来,很多选型问题在真实业务面前会自动给出答案。

3. 便签的“皮”:无边框窗口从搭起来到好用还差几步

3.1 透明无边框窗口的搭建

桌面便签的“皮”是一套无边框、可置顶、可透明的窗口。Tauri 里通过tauri.conf.json配置窗口,几个关键项是这样:

{ "app": { "windows": [ { "label": "note", "title": "Toast Notes", "width": 320, "height": 240, "decorations": false, "transparent": true, "alwaysOnTop": true, "skipTaskbar": true, "resizable": true, "shadow": false } ] } }

decorations: false去掉系统标题栏,transparent: true开启透明背景,skipTaskbar: true让便签不占任务栏位置,这样多个便签同时打开时,系统任务栏不会变成一片卡片堆。

去掉标题栏以后,拖动窗口就得自己实现。Tauri 2.x 里最省事的办法是在需要拖动的区域加>

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询