配置系统
配置文件
1. config.ini - 主配置文件
位置:resources/config/config.ini
ini
# 应用标题
electronTitle="vue3-simple-electron"
# 加载模式: remote(远程) 或 local(本地)
loadMode="remote"
# 本地资源路径
localWebPath="/resources/web"
# 远程URL地址
electronUrl="https://liumingxin.site"
# 应用版本
version="V1.0.0"
# 标题栏样式: default, hidden, hiddenInset, customButtonsOnHover
titleBarStyle="default"
# 自动隐藏菜单栏
autoHideMenuBar="true"
# 是否显示窗口边框
frame="true"
# 是否显示工具栏
toolbar="false"
# 子窗口是否最大化
childWindowMax="true"
# 是否启用 EXE 安装器
enableExeInstall="true"
# 启动时检查更新
checkForUpdatesOnStart="false"
# 更新服务器地址
updateVersionInfoUrl="http://127.0.0.1:30000/versions_info/"
# 启用子窗口菜单
enableChildWindowMenus="true"
# 显示主窗口右键菜单
showWindowRightMenu="true"
# 显示子窗口右键菜单
showChildWindowRightMenu="true"
# 显示缩放指示器
showZoomIndicator="true"
# 启用插件系统
enablePluginSystem="true"
# 插件自动加载
pluginAutoLoad="false"
# 插件沙箱超时时间(毫秒)
pluginSandboxTimeout="30000"
# 启用日志清理
enableLogCleanup="true"
# 日志保留天数
logRetentionDays="15"
# 定时清理日志时间
scheduleLogCleanupTime="18:00"2. proxy-rules.yaml - 代理配置
位置:resources/config/proxy-rules.yaml
yaml
# 是否启用代理
enabled: false
# 代理规则列表
rules:
# API 代理规则
- context: /api
target: http://localhost:8080
changeOrigin: true
pathRewrite:
^/api: /api/v1
logLevel: debug
# WebSocket 代理
- context: /socket
target: ws://localhost:9000
ws: true
changeOrigin: true
# 静态资源代理
- context: /assets
target: http://cdn.example.com
changeOrigin: true
headers:
X-Custom-Header: value3. apps-install.yaml - 应用安装配置
位置:resources/config/apps-install.yaml
用于配置需要自动安装的第三方应用程序。
yaml
# 应用安装列表
apps:
- name: '应用名称'
path: 'installers/app-installer.exe'
version: '1.0.0'
silent: true # 静默安装
autoStart: false # 安装后自动启动配置读取
配置读取器
javascript
// packages/main/src/config/reader-config.js
const ini = require('ini');
const fs = require('fs');
const path = require('path');
/**
* 读取配置文件
*/
function readConfig() {
const configPath = path.join(CONFIG_DIR_PATH, 'config.ini');
try {
const configContent = fs.readFileSync(configPath, 'utf-8');
return ini.parse(configContent);
} catch (error) {
logger.error('读取配置文件失败:', error);
return {};
}
}
/**
* 获取配置项值
* @param {string} key - 配置项名称
* @param {any} defaultValue - 默认值
*/
function getConfigValue(key, defaultValue = null) {
const config = readConfig();
if (config[key] === undefined) {
return defaultValue;
}
// 处理布尔值
if (config[key] === 'true') return true;
if (config[key] === 'false') return false;
// 处理数字
if (!isNaN(config[key]) && config[key] !== '') {
return Number(config[key]);
}
// 去除引号
return String(config[key]).replace(/^["']|["']$/g, '');
}
module.exports = {
readConfig,
getConfigValue,
APP_TITLE: getConfigValue('electronTitle', 'Electron App'),
CURRENT_VERSION: getConfigValue('version', 'V1.0.0'),
};使用示例
javascript
const { getConfigValue } = require('./config/reader-config');
// 读取加载模式
const loadMode = getConfigValue('loadMode', 'remote');
// 读取远程 URL
const electronUrl = getConfigValue('electronUrl');
// 读取布尔值
const checkForUpdates = getConfigValue('checkForUpdatesOnStart'); // true/false
// 读取数字
const logRetentionDays = getConfigValue('logRetentionDays', 30); // 15配置项详解
窗口配置
ini
# 标题栏样式
titleBarStyle="default"
# 可选值:
# - default: 默认样式
# - hidden: 隐藏标题栏
# - hiddenInset: 隐藏标题栏(macOS traffic lights)
# - customButtonsOnHover: 悬停显示按钮
# 自动隐藏菜单栏
autoHideMenuBar="true"
# 窗口边框
frame="true"
# 工具栏
toolbar="false"加载模式配置
ini
# 加载模式
loadMode="remote"
# remote: 远程模式,加载 electronUrl
# local: 本地模式,使用本地HTTP服务器
# 远程URL(remote模式使用)
electronUrl="https://liumingxin.site"
# 本地资源路径(local模式使用)
localWebPath="/resources/web"详见 加载模式文档
更新配置
ini
# 启动时检查更新
checkForUpdatesOnStart="false"
# 更新服务器地址
updateVersionInfoUrl="http://127.0.0.1:30000/versions_info/"详见 更新系统文档
插件系统配置
ini
# 启用插件系统
enablePluginSystem="true"
# 插件自动加载
pluginAutoLoad="false"
# 插件沙箱超时时间(毫秒)
pluginSandboxTimeout="30000"详见 插件通信文档
日志配置
ini
# 启用日志清理
enableLogCleanup="true"
# 日志保留天数
logRetentionDays="15"
# 定时清理日志时间(HH:mm格式)
scheduleLogCleanupTime="18:00"详见 日志系统文档
界面配置
ini
# 显示主窗口右键菜单
showWindowRightMenu="true"
# 显示子窗口右键菜单
showChildWindowRightMenu="true"
# 显示缩放指示器
showZoomIndicator="true"
# 启用子窗口菜单
enableChildWindowMenus="true"
# 子窗口默认最大化
childWindowMax="true"应用安装配置
ini
# 启用 EXE 安装器
enableExeInstall="true"代理配置
代理规则说明
yaml
enabled: true # 启用代理
rules:
- context: /api # 匹配路径
target: http://localhost:8080 # 目标服务器
changeOrigin: true # 改变请求源
pathRewrite: # 路径重写
^/api: /api/v1 # 将 /api 替换为 /api/v1
logLevel: debug # 日志级别代理选项
| 选项 | 类型 | 说明 | 默认值 |
|---|---|---|---|
context | string | 匹配路径前缀 | 必填 |
target | string | 目标服务器地址 | 必填 |
changeOrigin | boolean | 改变请求源 | false |
ws | boolean | 是否为 WebSocket | false |
pathRewrite | object | 路径重写规则 | {} |
logLevel | string | 日志级别 | 'info' |
headers | object | 自定义请求头 | {} |
timeout | number | 超时时间(ms) | 30000 |
WebSocket 代理
yaml
rules:
- context: /socket
target: ws://localhost:9000
ws: true # 启用 WebSocket
changeOrigin: true路径重写
yaml
rules:
- context: /api
target: http://localhost:8080
pathRewrite:
# 移除 /api 前缀
^/api: ''
# 替换为新路径
^/api: /v1/api
# 多个规则
^/old-path: /new-path
^/legacy: /v2自定义请求头
yaml
rules:
- context: /api
target: http://localhost:8080
headers:
Authorization: Bearer token123
X-Custom-Header: value
X-API-Key: your-api-key配置编辑
通过快捷键编辑
按 Ctrl+Alt+Shift+P (Windows/Linux) 或 Cmd+Alt+Shift+P (macOS) 打开配置编辑窗口。
详见 快捷键文档
配置编辑窗口
javascript
// packages/main/src/shortcut/update-config.html
// 提供可视化界面编辑 config.ini 文件功能:
- 可视化编辑配置项
- 实时验证配置值
- 保存后提示重启应用
编程方式修改
javascript
const fs = require('fs');
const ini = require('ini');
// 读取配置
const configPath = path.join(CONFIG_DIR_PATH, 'config.ini');
const config = ini.parse(fs.readFileSync(configPath, 'utf-8'));
// 修改配置
config.loadMode = 'local';
config.checkForUpdatesOnStart = 'true';
// 保存配置
fs.writeFileSync(configPath, ini.stringify(config));
// 重启应用使配置生效
app.relaunch();
app.exit(0);配置验证
配置项验证
javascript
/**
* 验证配置项
*/
function validateConfig(config) {
const errors = [];
// 验证加载模式
if (!['remote', 'local'].includes(config.loadMode)) {
errors.push('loadMode 必须是 remote 或 local');
}
// 验证远程 URL
if (config.loadMode === 'remote' && !config.electronUrl) {
errors.push('remote 模式需要配置 electronUrl');
}
// 验证数字配置
if (isNaN(config.logRetentionDays) || config.logRetentionDays < 1) {
errors.push('logRetentionDays 必须是正整数');
}
// 验证时间格式
if (!/^\d{2}:\d{2}$/.test(config.scheduleLogCleanupTime)) {
errors.push('scheduleLogCleanupTime 格式必须是 HH:mm');
}
return {
valid: errors.length === 0,
errors,
};
}使用验证
javascript
const config = readConfig();
const validation = validateConfig(config);
if (!validation.valid) {
logger.error('配置验证失败:', validation.errors);
// 使用默认配置或提示用户
}环境变量
环境变量支持
ini
# 使用环境变量
electronUrl="${ELECTRON_URL}"
updateVersionInfoUrl="${UPDATE_SERVER}"javascript
// 解析环境变量
function parseEnvVars(value) {
return value.replace(/\$\{(\w+)\}/g, (match, key) => {
return process.env[key] || match;
});
}
const url = parseEnvVars(config.electronUrl);.env 文件支持
bash
# .env
ELECTRON_URL=https://production.com
UPDATE_SERVER=https://updates.com
LOG_LEVEL=debugjavascript
require('dotenv').config();
// 现在可以使用 process.env.ELECTRON_URL配置优先级
配置加载优先级(从高到低):
- 环境变量 -
process.env.XXX - 命令行参数 -
--config-key=value - 配置文件 -
config.ini - 默认值 - 代码中的默认值
javascript
function getConfigValue(key, defaultValue) {
// 1. 环境变量
if (process.env[key.toUpperCase()]) {
return process.env[key.toUpperCase()];
}
// 2. 命令行参数
const argValue = getCommandLineArg(key);
if (argValue !== undefined) {
return argValue;
}
// 3. 配置文件
const config = readConfig();
if (config[key] !== undefined) {
return config[key];
}
// 4. 默认值
return defaultValue;
}配置热更新
监听配置文件变化
javascript
const chokidar = require('chokidar');
// 监听配置文件
const watcher = chokidar.watch(configPath, {
persistent: true,
});
watcher.on('change', (path) => {
logger.info('配置文件已更改:', path);
// 重新加载配置
reloadConfig();
// 通知渲染进程
BrowserWindow.getAllWindows().forEach((win) => {
win.webContents.send('config-changed');
});
});部分配置热更新
某些配置可以在运行时生效,无需重启:
javascript
// 可热更新的配置
const HOT_RELOAD_CONFIGS = ['showZoomIndicator', 'showWindowRightMenu', 'logLevel'];
function handleConfigChange(key, newValue) {
if (HOT_RELOAD_CONFIGS.includes(key)) {
// 立即应用新配置
applyConfig(key, newValue);
} else {
// 提示需要重启
dialog
.showMessageBox({
message: '配置已更改,需要重启应用才能生效',
buttons: ['立即重启', '稍后重启'],
})
.then((result) => {
if (result.response === 0) {
app.relaunch();
app.exit(0);
}
});
}
}最佳实践
1. 使用类型安全的配置读取
javascript
// 定义配置类型
const CONFIG_TYPES = {
loadMode: 'string',
checkForUpdatesOnStart: 'boolean',
logRetentionDays: 'number',
};
function getTypedConfig(key, defaultValue) {
const value = getConfigValue(key, defaultValue);
const type = CONFIG_TYPES[key];
if (type === 'boolean') {
return value === 'true' || value === true;
} else if (type === 'number') {
return Number(value);
}
return value;
}2. 配置缓存
javascript
let configCache = null;
let cacheTime = 0;
const CACHE_TTL = 5000; // 5秒
function getCachedConfig() {
const now = Date.now();
if (!configCache || now - cacheTime > CACHE_TTL) {
configCache = readConfig();
cacheTime = now;
}
return configCache;
}3. 配置备份
javascript
function backupConfig() {
const configPath = path.join(CONFIG_DIR_PATH, 'config.ini');
const backupPath = path.join(CONFIG_DIR_PATH, `config.ini.backup.${Date.now()}`);
fs.copyFileSync(configPath, backupPath);
logger.info('配置已备份:', backupPath);
}
// 修改配置前备份
function updateConfig(newConfig) {
backupConfig();
saveConfig(newConfig);
}4. 配置版本管理
ini
# config.ini
configVersion="1.0.0"javascript
function migrateConfig(config) {
const currentVersion = config.configVersion || '0.0.0';
// 从 0.x 迁移到 1.0
if (compareVersions(currentVersion, '1.0.0') < 0) {
config.newFeature = 'default';
config.configVersion = '1.0.0';
saveConfig(config);
}
}相关文件
resources/config/config.ini- 主配置文件resources/config/proxy-rules.yaml- 代理配置resources/config/apps-install.yaml- 应用安装配置packages/main/src/config/reader-config.js- 配置读取器packages/main/src/shortcut/update-config.html- 配置编辑界面