00 / 00

本地存储

区分桌面应用里的前端状态、app data、本地文件、Keychain 和后端数据

桌面应用很容易把”本地存储”混成一坨。模板只默认保存本地偏好,其他数据要按安全性和生命周期选存储位置。

常见存储位置

存储位置适合放什么不适合放什么
React state / TanStack Query页面临时状态、接口缓存需要重启后保留的数据
localStorage浏览器预览 fallback、小型非敏感偏好token、secret、重要业务数据
Tauri app data桌面偏好、草稿、缓存索引、本地配置明文密钥和高价值 secret
OS Keychain / Credential Storerefresh token、第三方 API key、敏感凭证大文件和普通 UI 状态
用户选择的文件夹用户明确要保存的导出文件应用内部配置
后端数据库账号、订单、权限、协作数据只属于本机的 UI 偏好

模板当前保存什么

模板只保存桌面偏好:

export type DesktopPreferences = {
  autoUpdateCheck: boolean;
  launchAtLogin: boolean;
  serverUrl: string;
  startMinimized: boolean;
  version: number;
  webUrl: string;
};

浏览器预览时保存在 localStorage。Tauri 原生窗口里保存在 app data 目录:

desktop-preferences.json

Rust 代码在:

products/01mvp/apps/desktop/src-tauri/src/lib.rs

TypeScript adapter 在:

products/01mvp/apps/desktop/src/runtime/preferences.ts

为什么不用 localStorage 存一切

桌面 WebView 里的 localStorage 放简单前端状态可以,但不适合当通用桌面存储:

  • 没法做版本迁移
  • 不适合放敏感凭证
  • 不适合大文件或缓存目录
  • 用户不好定位和排查
  • 换 WebView、清缓存或重装后行为不直观

稳定的桌面配置优先放 app data。敏感凭证再用 OS Keychain。

app data 适合什么

app data 目录适合:

  • 用户设置
  • 本地缓存索引
  • 最近打开的项目列表
  • 非敏感草稿
  • 本地任务状态
  • 可删除后重新生成的数据

模板里可以通过设置面板打开 app data 目录,方便新手理解数据保存在哪里。

敏感凭证怎么放

别把这些明文丢进 JSON:

  • 第三方 API key
  • refresh token
  • 支付密钥
  • 数据库连接串
  • 管理员令牌

如果产品需要本地保存敏感凭证,加 OS Keychain / Credential Store 插件,通过 src/runtime 封装。前端组件只调 adapter,不直接操作插件。

数据迁移

本地偏好带 version 字段:

const DESKTOP_PREFERENCES_VERSION = 1;

以后修改结构时按版本迁移:

  1. 读取旧 JSON
  2. 根据旧 version 补齐默认值或转换字段
  3. 写回新版本
  4. 保留 fallback,避免旧文件损坏导致 App 打不开

模板当前的 normalizeDesktopPreferences() 已经处理空值和默认值。

和后端数据的边界

账号、付费状态、订单、权限和协作数据放后端。本地只缓存展示用的数据,不能把本地缓存当权限判断来源。

原则:

  • 权限和计费以服务端为准
  • 本地偏好以 app data 为准
  • 敏感凭证走 Keychain
  • 大文件由用户选择目录或使用专门缓存目录
  • 可从后端重新拉取的数据可以缓存,但要能失效

验收

修改本地存储逻辑后,至少检查:

  • 浏览器预览 fallback 可用
  • Tauri 原生窗口能读写 app data
  • JSON 损坏时应用不会白屏
  • 改默认值后旧配置能正常补齐
  • 退出重开后设置仍然存在
  • 删除 app data 文件后能恢复默认配置

这篇文档有问题?