English version: README.en.md.
Tauri 2 + React 19 桌面应用脚手架,集成了 2026 年主流的工程化实践,开箱即用。
状态:
0.2.0。发布与更新流程见 docs/DEPLOYMENT.md,变更记录见 CHANGELOG.md。
| 层 | 选型 |
|---|---|
| UI | React 19 + TypeScript + Vite |
| 桌面壳 | Tauri 2(Rust) |
| 路由 | react-router v8 |
| 状态 | zustand(客户端)+ TanStack Query(服务端) |
| 样式 | Tailwind CSS v4 + shadcn/ui(Radix) |
| 规范 | ESLint 10(flat config)+ Prettier |
# 方式一:直接用模板创建新项目(无需 fork)
pnpm dlx degit mbr1024/dahl my-app && cd my-app && pnpm install
pnpm run tauri dev # 开发(首次编译 Rust 较慢)
# 方式二:在本仓库内开发
pnpm install
pnpm run tauri dev # 开发(首次编译 Rust 较慢)
pnpm run tauri build # 打包安装包模板默认名字是 Dahl。用模板创建自己的项目后,按以下清单改名(degit 拉取后无模板变量替换,需手动改 5 处):
| 要改的项 | 位置 |
|---|---|
| 包名 | package.json → name |
| Rust 包名 | src-tauri/Cargo.toml → package.name |
| 应用名 / 窗口标题 | src-tauri/tauri.conf.json → productName、app.windows[0].title |
| 应用唯一标识(决定安装路径/包 ID) | src-tauri/tauri.conf.json → identifier(如 com.acme.myapp) |
| deep-link scheme | src-tauri/tauri.conf.json → plugins.deep-link.identifiers,同步改 src-tauri/Info.plist 的 URL scheme |
| 应用图标 | 用 scripts/make-app-icon.py 从新图标素材生成 src-tauri/icons/ 全套(参照脚本顶部说明) |
改完跑 pnpm run tauri dev 确认应用名、窗口标题、dahl:// scheme 均已替换。若更换了 identifier,首次运行前建议清除旧 identifier 的配置残留(macOS 的 ~/Library/Application Support/ 下旧目录)。
本模板定位 桌面应用(macOS / Windows / Linux)。
src-tauri/icons/虽含 Android/iOS 素材,但 capabilities 与插件选择(autostart、window-state、updater、托盘)均按桌面设计,移动端不在支持范围。
pnpm run dev # 仅前端 dev server
pnpm run build # 前端构建
pnpm run typecheck # TypeScript 类型检查
pnpm run lint # ESLint
pnpm run lint:fix # ESLint 自动修复
pnpm run format # Prettier 格式化
pnpm run test # Vitest 单元测试
pnpm run test:coverage # 单元测试 + 覆盖率报告(HTML 输出到 coverage/)
pnpm run test:e2e # WebdriverIO 端到端测试(自动构建 debug 版后运行)
pnpm run changeset # 记录版本变更(自动生成版本 PR)
pnpm run tauri build # 打包安装包(macOS: .app/.dmg)基于 WebdriverIO + @wdio/tauri-service(embedded WebDriver,WebDriver server 内嵌于应用,
无需安装外部 driver),覆盖:应用启动、Rust 命令 invoke、路由导航、i18n 切换。
pnpm run test:e2e # 构建 debug 二进制后运行
pnpm run test:e2e:run # 已构建过时直接运行(CI 用)注意事项:
- 先关闭正在运行的 Dahl 实例(single-instance 插件会让新实例让位给旧进程)
- 测试插件(
tauri-plugin-wdio)仅在 dev/debug 构建注册,release 产物不含测试后门 - Linux 无显示环境需
xvfb-run;macOS/Windows 开箱即用 - 测试代码在
e2e/,配置见wdio.conf.ts,类型检查见tsconfig.e2e.json
单元测试覆盖率由 Vitest v8 统计(test:coverage),阈值配置在 vitest.config.ts
(当前为防回退基线,目标 80% 随测试增长逐步上调);CI 每次 push/PR 都会跑覆盖率并
上报 Codecov(激活后徽章可见)。
src/
├── routes/ # 页面级组件(一个路由一个文件)
├── components/
│ ├── ui/ # shadcn 生成的组件(勿手改)
│ ├── layout/ # 布局外壳、主题/语言 Provider
│ └── error-boundary.tsx # 全局错误边界
├── stores/ # zustand 全局状态(主题/语言,persist)
├── services/ # 数据请求层(TanStack Query + http 插件)
├── i18n/ # react-i18next(zh/en,默认中文)
├── hooks/ # 通用 hooks
├── lib/ # 工具函数(cn 等)
└── test/ # 测试 setup
src-tauri/
├── src/lib.rs # Rust 入口:插件注册、命令、托盘
├── capabilities/ # 权限配置(zero-trust,按需放开)
└── tauri.conf.json # 窗口、打包、updater、deep-link 配置
e2e/ # WebdriverIO 端到端测试(embedded WebDriver)
docs/ # 部署与运维文档(updater 配置等)
.github/workflows/ # CI:检查 / e2e / Linux 构建(tag 发布时三平台)
fs、dialog、store、window-state、clipboard-manager、
notification、single-instance、http、updater、log、autostart、
sql(SQLite)、shell、deep-link、opener
示例页(侧边栏 → 桌面能力)演示:Rust 命令 invoke、文件对话框、剪贴板、 系统通知、键值存储、SQLite 增删查、Shell 执行、深链接监听。
欢迎提交 Issue 与 PR!请先阅读 CONTRIBUTING.md(开发环境、提交规范、PR 流程), 安全漏洞报告见 SECURITY.md。
- 权限:Tauri 2 默认全拒绝。
clipboard-manager/sql/shell/deep-link的default权限集为空,使用对应 API 时需在capabilities/显式加allow-*权限(排查:看src-tauri/gen/schemas/acl-manifests.json) - 托盘:左键单击切换主窗口显隐,右键菜单可退出;关闭窗口会隐藏到托盘
- updater:以 GitHub Releases 作为更新源(endpoint 指向
latest.json),正式签名密钥已配置; 发布时 CI 自动签名并生成更新清单,完整流程见 docs/DEPLOYMENT.md - deep-link:scheme 为
dahl://,dev 模式测试需先在系统注册 scheme - 主题/语言:
src/stores/use-settings.ts控制,偏好持久化;默认中文(i18n 提供中英切换) - 提交:husky + lint-staged 在 pre-commit 自动执行 lint/format