aps-agent/Tauri迁移可行性评估.md

90 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Tauri 迁移可行性评估
> 评估日期:2026-09-02 · 基于 `apps/desktop/` 现状代码(Electron 43.2.0 + electron-builder 26.15.3)
> 结论先行:**技术可行,前端近乎零改动;真正的成本在 Rust 重写 sidecar 编排与离线升级体系(约 2,000 行久经测试的 JS),以及工厂离线 PC 的 WebView2 依赖风险。建议先做 1 周 PoC 再决策。**
---
## 1. 现状资产盘点(需要迁移的东西)
| 文件 | 行数 | Electron 耦合度 | 内容 |
|------|------|----------------|------|
| `main.cjs` | 659 | 🔴 高 | 窗口管理(自绘无边框)、单实例锁、15 个 IPC handler、~/.aps 目录布局、CSP 注入、导航守卫、nonce 请求头注入 |
| `sidecar.cjs` | 373 | 🟢 低(纯 Node) | SidecarManager:端口预留、nonce/audit token 轮换、子进程环境白名单清洗(Conda/Python 隔离)、健康探测、日志轮转(10MiB)、崩溃重启策略(上限 3 次 + 退避)、taskkill 进程树回收、父进程看门狗 |
| `updater.cjs` | 570 | 🟢 无(纯 Node,注释明确写明无 Electron 依赖) | 离线升级全流程:manifest 校验 → sha256 → 备份 → NSIS 静默安装 → 健康检查 + 版本比对 → 失败自动回滚 → 审计(本地 JSONL + 可选上报,含幂等键) |
| `upgrade-nonce.cjs` | 337 | 🟢 无(纯状态机) | 升级 nonce 续接协调器:pending 状态机(installing→verifying→verified/failed)、跨进程持久化、sidecar 重启后新 nonce 补验 |
| `preload.cjs` | 82 | 🔴 高 | contextBridge 暴露 `window.apsDesktop`(约 20 个方法) |
| 前端调用面 | — | — | `apsDesktop` 仅 7 个文件、25 处调用(App.tsx、client.ts、AppMenuBar.tsx、SkillConsole.tsx 等) |
| 测试资产 | ~48 项 node 测试 + 2 个冒烟脚本(803 + 187 行) | 🟡 中 | updater/sidecar/nonce 单测是纯 Node 可保留逻辑用例;NSIS 真装冒烟与 electron-builder 布局强耦合 |
**关键发现**:项目最初的模块化做得不错——`updater.cjs` 和 `upgrade-nonce.cjs` 是纯 Node 无 Electron 依赖,逻辑可整体搬迁;但它们仍需用 Rust 重写(Tauri 主进程没有 Node 运行时)。
## 2. 逐项映射:Electron → Tauri
### ✅ 原生支持 / 几乎免费(约 40%)
| 能力 | Tauri 对应 | 说明 |
|------|-----------|------|
| 前端复用 | 直接复用 `apps/web/dist` | React 产物零改动 |
| Python sidecar | 官方 sidecar 机制(`externalBin`) | PyInstaller 产物、`aps-sidecar.spec` 完全保留 |
| 无边框自绘窗口 | `decorations: false` + `data-tauri-drag-region` | 前端已有自绘顶栏(AppMenuBar),窗口控制走 `@tauri-apps/api/window`,无需 Rust |
| 单实例锁 | `tauri-plugin-single-instance` | 官方插件 |
| CSP 加固 | `tauri.conf.json` 内置 CSP 字段 | 比 Electron 的 session 注入更声明式 |
| 权限拒绝 / 导航限制 | Tauri webview 默认更封闭;外链走 opener 插件 | 安全姿态默认更好 |
| 中文菜单 | 现状已弃用原生菜单(web 顶栏呈现) | 无需迁移 |
| NSIS 安装包 | Tauri v2 支持 NSIS target,兼容 `/S` 静默 | 离线升级触发语义可保持 |
### ⚠️ 需要适配 / 中等工作量(约 30%)
| 能力 | 迁移方式 | 风险点 |
|------|---------|--------|
| `apsDesktop` 桥(25 处前端调用) | 写一个 `window.apsDesktop` 兼容层封装 `@tauri-apps/api`,前端 7 个文件不改 | 低 —— 调用面小是最大利好 |
| IPC handlers(15 个) | 窗口类(min/max/close/fullscreen)前端直接调 JS API;其余(get-home / get-device-id / pick-directory / 升级三件套)写成约 6-8 个 Rust command | 低 |
| nonce 请求头注入 | Electron 用 `session.webRequest` 拦截全部请求;Tauri 无此能力。**替代方案**:nonce 经桥暴露给前端,在 `api/client.ts`(已收口,仅 3 处调用面)统一注入 header | **中 —— 安全模型微调**:nonce 从"主进程持有、渲染进程不可见"变为"渲染进程可知"。实际暴露面等价(渲染进程本就能发带 nonce 的请求),但需安全评审确认 |
| NSIS 冒烟脚本(803 行) | Tauri NSIS 安装布局不同(无 `win-unpacked`、可执行文件名/路径变),脚本需适配重写 | 中 —— 脚本安全边界设计可复用 |
### 🔴 必须 Rust 重写(约 30%,成本集中在这里)
| 模块 | 重写估算 | 说明 |
|------|---------|------|
| SidecarManager(373 行 JS) | ~600 行 Rust,1-2 周 | 端口预留、nonce 轮换、**环境白名单清洗**(Conda/Python 隔离逻辑微妙,测试用例多)、健康探测、日志轮转、重启退避、taskkill 进程树、父进程看门狗。Tauri sidecar 只负责"拉起",编排全部自建 |
| Updater(570 行 JS) | ~800 行 Rust,2-3 周 | Tauri 官方 updater 插件面向**在线签名更新**,不适配本项目的 **U 盘/介质离线升级 + manifest + 备份回滚 + 幂等审计**流程,必须整体重写 |
| upgrade-nonce 协调器(337 行 JS) | ~400 行 Rust | 建议与 Rust 版 SidecarManager 合并(重启事件在同进程内,不再需要跨模块事件总线),可适度简化 |
| 测试体系重建 | 1 周 | 48 项 node 测试逻辑用例可翻译成 Rust 单测;打包冒烟(CDP 冒烟是 Electron 专属,需找 Tauri 等价手段或放弃) |
## 3. 风险清单(按严重度)
| # | 风险 | 严重度 | 说明与缓解 |
|---|------|--------|-----------|
| R1 | **WebView2 依赖 vs 工厂离线 PC** | 🔴 高 | Electron 自带 Chromium 零依赖;Tauri 依赖系统 WebView2。工厂现场老 Win10/离线机器可能没有。缓解:Tauri NSIS 支持内嵌 WebView2 离线引导(`embedFixedWebview2`,体积 +100MB 左右,会吃掉约一半的体积收益)。**这是决策的第一道门:先调查目标客户的机器现状** |
| R2 | 升级链路重写重新打开安全验证面 | 🟡 中高 | updater + nonce 协调器是经过 round-43~48 多轮加固、48 项测试、真装冒烟验证的资产。重写后所有边界场景(nonce 过期不误回滚、安装途中 sidecar 重启、应用重启续接)需重新验证 |
| R3 | 团队 Rust 能力 | 🟡 中 | 约 1,800 行 Rust 新增代码,含进程管理、文件哈希、Windows API(taskkill 等价) |
| R4 | 体积收益被 sidecar 稀释 | 🟡 中 | 567MB 解包中 Electron 壳约占 250-300MB,Python sidecar 占其余大头。换 Tauri 后安装包预计从 ~180MB 降至 ~60-80MB——有感知但不是数量级 |
| R5 | 过渡期双壳维护 | 🟢 低 | PoC 期间 Electron 继续演进,需冻结桌面安全需求或接受两次实现 |
## 4. 工作量估算
| 里程碑 | 内容 | 工期 |
|--------|------|------|
| M0 PoC | Tauri 壳 + web dist + sidecar 拉起 + 健康探测 + 兼容桥跑通主界面 | **3-5 天** |
| M1 | Rust 版 SidecarManager 完整对齐(环境清洗/重启/日志/看门狗)+ 单测 | 1-2 周 |
| M2 | IPC command + 窗口态 + 单实例 + CSP + nonce header 方案落地 | 3-5 天 |
| M3 | Rust 版离线 Updater + nonce 协调器 + 测试翻译 | 2-3 周 |
| M4 | 打包链路(NSIS/SBOM/冒烟)+ 验证矩阵重跑(冷启动/Defender/升级回滚/中文路径) | 1-2 周 |
| **合计** | PoC 1 周内可见证;**全量对齐约 6-9 周**(1 人) | |
## 5. 决策建议
```
第一道门(先做):目标客户机器 WebView2 现状调查
├─ 现场 Win10/11 均有 WebView2(或可联网/可预装)
│ → 启动 M0 PoC(1 周),跑通则排期 6-9 周全量迁移
└─ 大量离线老机器无 WebView2
→ 维持 Electron,转向"瘦身"替代方案:
① sidecar onedir 裁剪(排除未用包,通常可省 100MB+)
② electron-builder asar 压缩 + NSIS 高压缩
③ 移除安装包中未用的 Chromium 语言包/locales
```
**不建议**在升级链路(R2)没有完整测试覆盖前双壳并行发布;迁移应一次性切换、单壳维护。