Node.js Conf 配置库要点分析 和 使用注意事项

Electron 中有个 electron-store,深入源码去看,发现其依赖Node.js的配置库 Conf,只是在这个基础上追加主进程和其他渲染进程 proload.js 通信的环节,让你在使用时无感这个过程,实际上Electron-store 超简单,就是在主进程中直接获取,在渲染进程中,通过sendSync获取下面这个参数,主进程必须实例化一个监听事件,渲染进程从这边获取用户目录和 App 版本

const appData = {
		defaultCwd: app.getPath('userData'),
		appVersion: app.getVersion()
	};

Conf的各类配置

选项名

类型

默认值

说明

示例

defaults

object

undefined

指定配置的默认值,当配置文件中缺少某键时返回默认值。确保关键配置始终有值,防止程序因缺失配置出错。

const config = new Conf({ defaults: { theme: 'dark', notifications: true } });console.log(config.get('theme')); // 'dark'

configName

string

'config'

指定配置文件名称(不含扩展名),生成的文件名为

configName.json

const config = new Conf({ configName: 'settings' }); // 生成 settings.json

projectName

string

从最近的

package.json

name

字段获取

指定项目名称,用于确定配置文件存储路径(通常在系统用户配置目录下的

project-name

文件夹)。避免不同项目配置冲突。

const config = new Conf({ projectName: 'my-app' }); // 存储在 my-app 文件夹

projectVersion

string

从最近的

package.json

version

字段获取

指定项目版本,存储为配置文件元数据,用于配置迁移或版本兼容性处理。

const config = new Conf({ projectVersion: '1.0.0' });

cwd

string

process.cwd()

指定查找

package.json

的目录,影响

projectName

projectVersion

的自动获取,或用于自定义配置文件路径。

const config = new Conf({ cwd: '/path/to/project' });

projectSuffix

string

'nodejs'

在项目名称后附加后缀,影响存储路径(常见于 Windows 等系统)。可设为空字符串

''

移除后缀,或自定义后缀。

const config = new Conf({ projectName: 'my-app', projectSuffix: 'prod' }); // 路径含 my-app-prod

fileExtension

string

'json'

指定配置文件扩展名,默认为

.json

。可配合

serialize

deserialize

使用其他格式。

const config = new Conf({ fileExtension: 'conf' }); // 生成 config.conf

accessProperties

object

undefined

高级功能,允许通过点状路径(dot-notation)直接访问嵌套属性,映射到顶层属性。

const config = new Conf({ accessProperties: { size: 'window.size' } });config.size = { width: 100, height: 200 };console.log(config.get('window.size')); // { width: 100, height: 200 }

watch

boolean

false

启用配置文件变动监听。若设为

true

,当外部修改配置文件(如手动编辑 JSON)时,

conf

自动重新加载,并可通过

onDidChange

事件响应变化。

const config = new Conf({ watch: true });config.onDidChange('port', (newValue, oldValue) => console.log(`Port changed from ${oldValue} to ${newValue}`));

serialize

function

value => JSON.stringify(value, null, '\t')

自定义序列化函数,在写入配置文件前将数据转换为字符串。默认使用带缩进的 JSON 格式。

const config = new Conf({ serialize: value => JSON.stringify(value) }); // 无缩进 JSON

deserialize

function

value => JSON.parse(value)

自定义解析函数,在读取配置文件后将字符串转换为 对象。默认使用

JSON.parse

const config = new Conf({ deserialize: text => JSON.parse(text.replace(/'/g, '"')) });

encryptionKey

`string

Buffer

object`

undefined

schema

object

undefined

定义 JSON Schema 验证配置数据,需为 JSON Schema 的

properties

对象。每个键对应配置项,值定义类型、约束及默认值。默认值会被

defaults

覆盖。

const schema = { foo: { type: 'number', maximum: 100, minimum: 1, default: 50 } };const config = new Conf({ schema });config.set('foo', 'invalid'); // 抛出错误

accessPropertiesByDotNotation

boolean

true

控制是否支持点状路径访问嵌套属性。若为

false

,点状字符串(如

foo.bar

)被视为单一键。

const config = new Conf({ accessPropertiesByDotNotation: false });config.set('foo.bar', 'baz');console.log(config.get('foo.bar')); // 'baz'

migrations

object

undefined

定义版本迁移函数,键为版本号,值为迁移函数。需配合

projectVersion

使用,处理旧版本配置升级。

const config = new Conf({ migrations: { '2.0.0': store => store.set('newKey', 'value') }, projectVersion: '2.0.0' });

关键功能说明

  1. 文件变动监听:

    • 通过 watch: true 启用监听功能,结合 onDidChange 方法可实时响应配置变化。

    • 示例场景:当用户手动编辑 config.json 文件(如更改端口号),程序可自动检测并重启服务以应用新配置。

  2. 加密存储:

    • 使用 encryptionKey 保护敏感数据,但需注意密钥管理安全,避免硬编码在代码中。

  3. 嵌套属性访问:

    • 默认支持点状路径(如 config.get('foo.bar')),通过 accessPropertiesByDotNotation 可禁用,或用 accessProperties 映射属性。

  4. 默认值与验证:

    • defaults 提供兜底值,schema 确保数据格式正确,结合使用可提高配置可靠性。

  5. 自定义序列化/反序列化:

    • 通过 serialize 和 deserialize 支持非 JSON 格式(如 YAML),但需自行实现格式转换逻辑。

使用注意事项

  • 权限问题:设置 projectName 和 projectSuffix 时,确保进程有权读写系统配置目录(如 ~/Library/Preferences 或 ~/.config)。运行脚本时避免混用 sudo 和非 sudo,否则可能导致权限错误。

  • 性能考虑:启用 watch 会增加文件系统监控开销,适合动态配置场景;若配置静态,可禁用以提升性能。

  • 加密安全性:encryptionKey 仅用于数据混淆,非强加密。敏感数据建议结合其他安全措施(如环境变量或密钥管理服务)。

  • 版本迁移:使用 migrations 时,确保 projectVersion 准确,以避免重复执行迁移逻辑。

示例综合应用

以下是一个综合示例,展示如何使用多个选项实现配置管理、监听和加密:

const Conf = require('conf');

const config = new Conf({
  configName: 'app-config',
  projectName: 'my-app',
  projectSuffix: '',
  watch: true,
  encryptionKey: 'my-secret-key',
  defaults: {
    port: 3000,
    theme: 'light'
  },
  schema: {
    port: { type: 'number', minimum: 1024, maximum: 65535, default: 3000 },
    theme: { type: 'string', enum: ['light', 'dark'] }
  }
});

// 监听配置变化
config.onDidChange('port', (newValue, oldValue) => {
  console.log(`Port changed from ${oldValue} to ${newValue}`);
  // 例如:重启服务器以应用新端口
});

// 设置配置
config.set('port', 8080); // 自动写入加密后的 app-config.json
console.log(config.get('port')); // 8080
console.log(config.get('theme')); // 'light'(来自 defaults)

Conf 的迁移逻辑

  1. config.json 文件只保留最后升级的版本号,若没有配置migrations和projectVersion两个字段,则config.json中不会出现__internal__.migrations.version字段
  2. 遵循连续性升级规则,会将当前的版本号与升级列表版本号一一比对,获得需要升级的版本逻辑
const Store = require('electron-store');
const path = require('path');
const fs = require('fs');

// 初始化 electron-store 实例
const store = new Store({
  // 项目名称,决定配置文件存储路径(如 ~/.config/my-app/config.json)
  projectName: 'my-app',

  // 目标版本号,指定要迁移到的版本
  projectVersion: '1.1.0',

  // 配置文件名(默认 config.json)
  configName: 'config',

  // 文件扩展名(默认 json)
  fileExtension: 'json',

  // 配置存储目录(可选,默认使用 env-paths 推断)
  cwd: path.join(__dirname, 'config'),

  // 启用文件监听,响应外部修改
  watch: true,

  // 默认配置值
  defaults: {
    theme: 'light',
    port: 3000
  },

  // JSON Schema 验证(可选,确保配置格式正确)
  schema: {
    theme: {
      type: 'string',
      enum: ['light', 'dark'],
      default: 'light'
    },
    port: {
      type: 'number',
      minimum: 1024,
      maximum: 65535,
      default: 3000
    },
    featureA: {
      type: 'boolean',
      default: false
    },
    featureB: {
      type: 'string',
      default: 'disabled'
    }
  },

  // 迁移规则,定义版本升级逻辑
  migrations: {
    '1.0.0': store => {
      console.log('Migrating to 1.0.0');
      // 添加新配置项
      store.set('featureA', true);
      // 示例:重命名旧键
      if (store.has('oldKey')) {
        store.set('newKey', store.get('oldKey'));
        store.delete('oldKey');
      }
    },
    '1.1.0': store => {
      console.log('Migrating to 1.1.0');
      // 添加或更新配置项
      store.set('featureB', 'enabled');
      // 示例:转换配置格式
      if (store.has('theme')) {
        store.set('theme', store.get('theme').toLowerCase());
      }
    }
  },

  // 在每次迁移前执行的钩子,用于调试或日志记录
  beforeEachMigration: (store, { fromVersion, toVersion, finalVersion, versions }) => {
    console.log(`Migrating from ${fromVersion} to ${toVersion} (final: ${finalVersion}, versions: ${versions.join(', ')})`);
  },

  // 序列化/反序列化(可选,定制 JSON 格式)
  serialize: value => JSON.stringify(value, null, 2), // 美化 JSON 输出
  deserialize: value => JSON.parse(value),

  // 文件权限(默认 0o666)
  configFileMode: 0o666,

  // 是否清除无效配置(例如,JSON 解析错误时)
  clearInvalidConfig: true,

  // 是否启用点状路径访问(默认 true)
  accessPropertiesByDotNotation: true
});

// 监听配置文件变化(需要 watch: true)
store.onDidAnyChange(() => {
  console.log('Config file changed externally, reloading...');
  console.log('Current config:', store.store);
});

// 示例:监听特定键的变化
store.onDidChange('theme', (newValue, oldValue) => {
  console.log(`Theme changed from ${oldValue} to ${newValue}`);
});

// 示例:操作配置
console.log('Initial config:', store.store);
store.set('port', 8080); // 更新配置,自动写入 config.json
console.log('Updated port:', store.get('port'));

// 检查迁移版本
console.log('Current version:', store.get('__internal__.migrations.version'));

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

森叶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值