Nidalee 工程化实践:类型一致性、构建解耦、可观测与极致 DX

约 6 分钟阅读

要点速览

  • 类型同源:Rust → 前端类型同步,消除“灰度”与兼容成本。
  • 构建解耦:按生态拆包与场景化插件,提升冷启动与缓存命中。
  • 可观测统一:事件/错误建模一致,问题可定位、可回放。
  • 缓存与失效:Vue Query 统一 key/时效策略,既新鲜也克制。
  • CI/CD:一次配置,稳定输出可复现产物。

工程化四重奏:让规模与效率并行

1) 类型一致性:前后端同源,消除“灰度”

  • Rust → 前端类型同步:src-tauri 单测输出类型文件,脚本 scripts/sync-types.mjs 同步至 types/;避免「接口变更但前端不知」的灰度问题。
  • 前端以 env.d.ts/global.d.ts 明确运行时约束,减少 any 扩散;组合式函数以返回类型为主线,提升可读性。

示例(同步脚本伪代码):

ts
// scripts/sync-types.mjs(示意)
import { writeFile } from 'node:fs/promises'
const rustTypes = await runRustTestAndCollectTypes()
await writeFile('types/lcu.d.ts', rustTypes)

2) 构建与性能:把包拆在“该拆”的地方

  • Vite Rollup manualChunks:按生态域拆分(Vue/Pinia/TanStack/Tailwind/通用),高复用包冷启动更快、缓存更稳。
  • Dev/Prod 插件差异:
    • Dev:Vue DevTools、AutoImport、Components 提升 DX。
    • Prod:去除 console、可选体积可视化。

manualChunks 配置(节选):

ts
// vite.config.ts(节选)
manualChunks(id) {
  if (id.includes('node_modules')) {
    if (id.includes('vue')) return 'vendor_vue'
    if (id.includes('pinia')) return 'vendor_pinia'
    if (id.includes('@tanstack')) return 'vendor_tanstack'
    if (id.includes('tailwind-merge') || id.includes('tw-animate-css') || id.includes('tailwind-scrollbar'))
      return 'vendor_tailwind'
    return 'vendor'
  }
}

3) 可观测与错误处理:先可见,后可控

  • 活动日志:统一的 useActivityLogger,贯穿连接、对战流程、自动化行为,既用于 UI 面板展示,也用于问题定位。
  • 错误映射与边界:IPC 命令做输入校验与错误归一映射;领域服务内部用结果类型与错误类型枚举,减少“字符串比较”。

统一日志(节选):

ts
// useActivityLogger.ts(示意)
export function useActivityLogger() {
  const logs = ref<ActivityLog[]>([])
  function log(event: ActivityLog) {
    logs.value.push({ ...event, time: Date.now() })
  }
  return { logs, log }
}

事件与错误的统一建模:说同一种语言

  • 活动事件(Activity):标准字段包括 type | scope | detail | time | level,用于面板/导出与告警;
  • 错误(Error):采用分层枚举,如 Transport | Lcu | Parse | Timeout | Unknown,便于聚合统计与定位;
  • 日志采样:对高频事件做采样(例如 1/10),降低渲染压力与内存占用。

4) DX 与可维护性:开发者体验就是生产力

  • 目录按域划分,features/composables/ 按功能聚合,减少跨模块耦合。
  • UI 采用 shadcn-vue + Tailwind + 主题系统,既能快速搭建,又能统一风格。
  • Lint:oxlint + eslint 双线;prettier 保证风格一致;vue-tsc 做 SFC 类型校验。

CI/CD 与发布:一次配置,稳定输出

  • GitHub Actions:
    • Lint/Type Check → Build →(可选)体积分析 → 产物上传。
    • Tauri 打包:pnpm tauri build,产出 MSI/DMG 等安装包。
  • 版本与变更:使用 tag 触发发布;附带 RELEASE.md 指引,确保变更可追踪。

缓存策略与失效:既新鲜,也克制

  • Vue Query:
    • staleTime/gcTime 按域设定;
    • 使用 invalidateQueries 精准失效;
    • 对于非关键数据,使用 suspense + skeleton 提升感知。
  • 本地持久化:仅对设置与低敏元数据持久化,避免缓存“脏”状态跨会话污染。

实战 Tips

  • 轮询合并:unified_polling 将多源轮询聚拢管理,减少资源浪费与竞态。
  • 缓存约定:基于 @tanstack/vue-query 的 key 规范与过期策略统一,配合 useCachedQuery 下沉公共行为。
  • 变更隔离:新域 → 新目录,不在现有目录“硬塞”逻辑;减少回归面。

发布与质量 Checklist

  • Rust → 前端类型同步已通过(无 any/隐式类型)。
  • 构建拆包与插件策略按环境生效(无多余 console)。
  • 关键事件/错误纳入统一模型并可导出。
  • 缓存策略含 staleTime/gcTime,失效路径明确。
  • CI/CD 产物可复现(版本、构建信息、变更记录完整)。

延伸阅读

结语:不是炫技,是确定性

工程化不是炫技,而是稳定交付的保障。Nidalee 的这些做法能让项目规模化后仍保持可控与高效,适合在任何 Tauri/Vue 的桌面端项目中复用。

相关文章