mirror of
https://github.com/linshenkx/prompt-optimizer.git
synced 2026-05-08 06:28:50 +08:00
- 重构更新器,移除状态缓存,优化检查流程,改为每次启动时重新检测。 - 优化预览版提示逻辑和界面样式,增加版本号和提示信息的视觉区分。 - 移除`useElectronAPI` Hook,简化 Electron API 访问,直接使用 `window.electronAPI`。 - 调整 Release Notes 生成逻辑,修复检出代码问题,获取完整 git 历史和所有 tags。 - 优化版本忽略功能,`useUpdater`改为单例模式,支持预览版过滤。 - 移除build:parallel脚本中的build:desktop-only任务。 docs(dev): 更新桌面端自动更新系统设计文档 - 新增系统设计文档,描述自动更新系统的架构和界面布局。 - 补充 electron-updater 版本号说明,推荐使用 SemVer 2.0.0 标准。
5.4 KiB
5.4 KiB
Electron API 重构与回滚经验记录
📅 时间线
- 2025-07-14: 发现版本检查功能报错 "Failed to check versions"
- 重构提交:
12f6f49- "feat(ui): 添加 Electron API Hook并重构更新管理" - 问题根源: 过度抽象导致的架构复杂性和 bug
🚨 问题描述
症状
useUpdater.ts:224 [useUpdater] Error checking all versions: Error: Failed to check versions
at g (useUpdater.ts:128:15)
主进程日志正常
[DESKTOP] [2025-07-14 00:20:57] [info] Unified version check completed: { stable: '1.2.5', prerelease: '1.2.5' }
前端收到的响应
{
currentVersion: '1.2.0',
stable: { hasUpdate: true, remoteVersion: '1.2.5', ... },
prerelease: { hasUpdate: true, remoteVersion: '1.2.5', ... }
}
// 但是 response.success 是 undefined
🔍 根本原因分析
重构前(工作正常)
// 简单直接
const results = await window.electronAPI!.updater.checkAllVersions()
重构后(引入问题)
// 过度抽象
const { updater } = useElectronAPI()
const response = await updater.checkAllVersions()
if (!response.success) { // response.success 是 undefined
throw new Error(response.error || 'Failed to check versions')
}
const results = response.data
问题链条
- useUpdater.ts 调用
getElectronAPI()而不是useElectronAPI() - getElectronAPI() 直接返回
window.electronAPI,绕过了包装器 - preload.js 返回
result.data(直接数据) - useElectronAPI.ts 期望
{success, data, error}格式 - 数据格式不匹配 导致
response.success为undefined
🎯 重构的初衷 vs 实际效果
初衷
- 避免类型错误和 IDE 警告
- 提供类型安全的 Electron API 访问
实际效果
- 引入了过度复杂的抽象层
- 增加了调试难度
- 创造了新的 bug
- 维护成本大幅增加
🔄 回滚操作记录
1. 删除过度抽象文件
rm packages/ui/src/composables/useElectronAPI.ts
2. 回滚 useUpdater.ts
- 移除
useElectronAPI导入 - 将所有
electronUpdater改为window.electronAPI.updater - 将所有
electronShell改为window.electronAPI.shell - 将所有
electronOn/electronOff改为window.electronAPI.on/off - 移除复杂的响应格式检查
3. 简化类型定义
// packages/ui/src/types/electron.d.ts
interface UpdaterAPI {
checkAllVersions(): Promise<{
currentVersion: string
stable?: { remoteVersion?: string, hasUpdate?: boolean, ... }
prerelease?: { remoteVersion?: string, hasUpdate?: boolean, ... }
}>
installUpdate(): Promise<void>
ignoreVersion(version: string, versionType?: 'stable' | 'prerelease'): Promise<void>
}
interface ShellAPI {
openExternal(url: string): Promise<void>
}
4. 保持 preload.js 简单
checkAllVersions: async () => {
const result = await withTimeout(
ipcRenderer.invoke(IPC_EVENTS.UPDATE_CHECK_ALL_VERSIONS),
60000
);
if (!result.success) {
throw new Error(result.error);
}
return result.data; // 直接返回数据
}
📚 经验教训
❌ 过度工程化的问题
- 复杂度爆炸: 为了解决简单问题引入复杂架构
- 调试困难: 多层抽象使问题定位变得复杂
- 维护成本: 需要维护额外的 Hook、类型定义、包装逻辑
- 新 bug 源: 抽象层本身成为 bug 的来源
✅ 正确的解决方案
- 简单的类型定义: 通过完善
electron.d.ts解决 IDE 警告 - 直接 API 调用: 保持代码简洁明了
- 最小化抽象: 只在真正需要时才引入抽象
🎯 设计原则
- KISS 原则: Keep It Simple, Stupid
- YAGNI 原则: You Aren't Gonna Need It
- 优先解决核心问题: 类型安全 ≠ 复杂抽象
- 渐进式改进: 从简单开始,必要时再抽象
🔧 最佳实践
解决 IDE 警告的正确方法
// ✅ 正确:完善类型定义
declare global {
interface Window {
electronAPI: {
updater: UpdaterAPI
shell: ShellAPI
on: (event: string, callback: Function) => void
off: (event: string, callback: Function) => void
}
}
}
// ✅ 正确:直接使用
const result = await window.electronAPI.updater.checkAllVersions()
避免过度抽象
// ❌ 错误:不必要的包装
const { updater } = useElectronAPI()
const response = await updater.checkAllVersions()
const result = response.data
// ✅ 正确:直接调用
const result = await window.electronAPI.updater.checkAllVersions()
🎉 结果
回滚后的优势
- 代码行数减少: 删除了 100+ 行的包装代码
- 调试简化: 问题直接定位到源头
- 类型安全: 通过类型定义实现,无运行时开销
- 维护简单: 减少了抽象层的维护负担
性能提升
- 减少函数调用: 直接 API 调用,无包装开销
- 减少内存占用: 无额外的包装对象
- 提高可读性: 代码意图更加明确
💡 未来指导原则
- 先解决问题,再考虑抽象
- 类型安全通过类型定义实现,而非运行时包装
- 保持 API 调用的直接性和透明性
- 抽象必须有明确的价值,而非为了抽象而抽象
- 重构前要充分评估复杂度收益比
教训: 有时候最好的重构就是不重构。简单的问题用简单的方法解决。