一句话:Electron 应用的简单数据持久化——用户偏好、应用状态、缓存等,存为 JSON 文件。5.0k stars,sindresorhus 出品,底层基于其通用库 conf。

定位与选型

需求方案
用户偏好、窗口位置、简单配置(KB~MB 级)electron-store ✅
大量结构化数据、需要查询SQLite(better-sqlite3)/ IndexedDB(渲染进程)
需要多窗口实时同步的复杂状态IPC + 自建 store / Redux

特点:零配置、主进程渲染进程都能用(渲染进程经 IPC 或直接用)、支持 schema 校验、加密、原子写入、变更监听、数据迁移。

快速开始

npm install electron-store

主进程(注意 v11 是 ESM):

import Store from 'electron-store'
 
const store = new Store({
  defaults: {
    theme: 'system',
    window: { width: 800, height: 600 }
  }
})
 
store.set('theme', 'dark')
store.get('theme')                    // 'dark'
store.get('window.width')             // 800,支持路径式取值
store.set('window', { ...store.get('window'), width: 1024 })
store.delete('theme')
store.clear()

持久化位置:app.getPath('userData') 下的 config.json(文件名可配)。

常用配置

const store = new Store({
  name: 'settings',            // 文件名(默认 config)
  cwd: '/custom/dir',          // 自定义目录
  defaults: { foo: 'bar' },    // 默认值
  schema: {                    // JSON Schema 校验(底层 ajv)
    theme: { type: 'string', enum: ['system', 'light', 'dark'] }
  },
  encryptionKey: 'secret',     // 简单加密(异或级别,防肉眼不防破解)
  watch: true                  // 监听文件变更(多窗口/多进程同步场景)
})

数据迁移(应用升级时改结构)

const store = new Store({
  migrations: {
    '1.1.0': (store) => {
      store.set('debugMode', store.get('debug', false))
      store.delete('debug')
    }
  }
})

按版本号顺序执行,只跑一次——应用升级改配置结构的标准做法。

与 Electron API 的配合

窗口位置记忆(经典用法)

import { app, BrowserWindow } from 'electron'
import Store from 'electron-store'
 
const store = new Store()
 
app.whenReady().then(() => {
  const { width = 800, height = 600 } = store.get('window', {})
  const win = new BrowserWindow({ width, height })
  win.on('close', () => {
    const { width, height } = win.getBounds()
    store.set('window', { width, height })
  })
  win.loadFile('index.html')
})

渲染进程读写(经 IPC,符合安全模型)

// preload.js
contextBridge.exposeInMainWorld('settings', {
  get: (key) => ipcRenderer.invoke('store:get', key),
  set: (key, value) => ipcRenderer.invoke('store:set', key, value)
})
 
// main.js
ipcMain.handle('store:get', (_e, key) => store.get(key))
ipcMain.handle('store:set', (_e, key, value) => { store.set(key, value) })

不要为了省事开 nodeIntegration 让渲染进程直接 require electron-store——违反 06-security-performance 安全清单。渲染进程也有轻量替代:直接读写 localStorage(不跨窗口、随缓存目录走)。

常见坑

  • v9+ 纯 ESM:主进程 require('electron-store') 会报错,需 import 或 await import();CommonJS 项目要么改 ESM("type": "module"),要么用构建工具(electron-vite 打包后不受限)
  • 加密只是防肉眼窥视,敏感凭据应走系统钥匙串(safeStorage API)
  • 大对象频繁 set 会整文件重写,高频写入场景换 SQLite
  • 多窗口直接各自 new Store() 读的是同一文件,并发写有覆盖风险,写操作收敛到主进程

相关