refactor: 迁移至 electron-vite 官方推荐目录结构

- electron/* -> src/main/* (主进程)
- electron/preload.ts -> src/preload/index.ts (预加载)
- src/electron-api.d.ts -> src/preload/index.d.ts (类型声明)
- src/* -> src/renderer/src/* (渲染进程)
- src/index.html -> src/renderer/index.html
- electron.vite.config.ts 简化为自动入口检测 (零配置)
- tsconfig.app.json -> tsconfig.web.json, 更新 includes/paths
- 构建产物 dist-electron/ -> out/ (修复 main/preload 输出覆盖 bug)
- 更新 package.json main 字段 + electron-builder files
- 更新 .gitignore + eslint ignores
- 更新 AGENTS.md 架构文档
This commit is contained in:
2026-07-10 23:46:34 +08:00
parent 157af4399f
commit eda30250c6
71 changed files with 112 additions and 127 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
node_modules/
dist-electron/
out/
release/
dist/
*.log
@@ -15,7 +15,7 @@ yarn-error.log*
*.njsproj
*.sln
# Legacy codebase archived Vue 2 version, not part of v2 build
# Legacy codebase - archived Vue 2 version, not part of v2 build
legacy/
# Brainstorming artifacts
+21 -16
View File
@@ -6,10 +6,10 @@ Fork of [AnotherRedisDesktopManager](https://github.com/qishibo/AnotherRedisDesk
## Stack
- **Shell:** Electron 43 (`electron/main.ts`)
- **Preload:** `electron/preload.ts` (contextBridge, typed API)
- **Renderer:** Vue 3 + Pinia + Element Plus + Vue Router (`src/`)
- **IPC types:** `src/electron-api.d.ts` (ElectronAPI interface, global Window augmentation)
- **Shell:** Electron 43 (`src/main/index.ts`)
- **Preload:** `src/preload/index.ts` (contextBridge, typed API)
- **Renderer:** Vue 3 + Pinia + Element Plus + Vue Router (`src/renderer/src/`)
- **IPC types:** `src/preload/index.d.ts` (ElectronAPI interface, global Window augmentation)
- **Build:** electron-vite + Vite 6 + TypeScript 5
- **Redis client:** ioredis 5 (main process only)
- **Persistence:** electron-store + safeStorage (credentials)
@@ -18,7 +18,7 @@ Fork of [AnotherRedisDesktopManager](https://github.com/qishibo/AnotherRedisDesk
```bash
npm run dev # electron-vite dev (HMR, renderer on :5173)
npm run build # production build -> dist-electron/
npm run build # production build -> out/
npm start # preview built app
npm run build:unpack # build + electron-builder --dir
npm run build:win # build + electron-builder --win
@@ -30,9 +30,8 @@ npm run lint # eslint --fix
## Architecture
```
Electron main (electron/)
├── main.ts # Window creation, app lifecycle
├── preload.ts # contextBridge.exposeInMainWorld
Electron main (src/main/)
├── index.ts # Window creation, app lifecycle
├── ipc-handlers.ts # all IPC channel handlers
├── store.ts # electron-store (connections, settings)
├── credential.ts # safeStorage encrypt/decrypt
@@ -53,11 +52,16 @@ Electron main (electron/)
├── commandLogger.ts # command execution log
└── format.ts # value decode/format detection
Renderer (src/)
Preload (src/preload/)
├── index.ts # contextBridge.exposeInMainWorld
└── index.d.ts # ElectronAPI type declarations
Renderer (src/renderer/)
├── index.html # Vite entry HTML
└── src/
├── main.ts # Vue 3 bootstrap (Pinia, Element Plus)
├── App.vue # Shell layout (TitleBar + Sidebar + MainArea + StatusBar)
├── env.d.ts # Vite client + *.vue / *.css module declarations
├── electron-api.d.ts # ElectronAPI interface + global Window augmentation
├── stores/
│ ├── app.ts # theme, fontSize, scanCount
│ ├── connection.ts # connections CRUD, connect/disconnect, health check
@@ -203,19 +207,20 @@ Renderer (src/)
## Build config
- `electron.vite.config.ts` defines three build targets: main, preload, renderer
- Main + preload output to `dist-electron/`; renderer to `dist-electron/renderer/`
- Entry points auto-detected: `src/main/index.ts`, `src/preload/index.ts`, `src/renderer/index.html`
- Build output: `out/main/`, `out/preload/`, `out/renderer/`
- electron-builder packages into `release/`
- Renderer dev server runs on port 5173
- Main/preload use `externalizeDepsPlugin()` to keep node_modules external
- `@renderer` alias resolves to `src`
- `@renderer` alias resolves to `src/renderer/src`
## TypeScript
- Root `tsconfig.json` references `tsconfig.node.json` (main + preload) and `tsconfig.app.json` (renderer)
- Node target (`tsconfig.node.json`) includes `electron/**/*` + `electron.vite.config.ts`
- App target (`tsconfig.app.json`) includes `src/**/*`
- Root `tsconfig.json` references `tsconfig.node.json` (main + preload) and `tsconfig.web.json` (renderer)
- Node target (`tsconfig.node.json`) includes `src/main/**/*`, `src/preload/**/*.ts`, `electron.vite.config.ts`
- Web target (`tsconfig.web.json`) includes `src/renderer/src/**/*`, `src/preload/**/*.d.ts`
- Both use `verbatimModuleSyntax` (type-only imports required) and `moduleResolution: "bundler"`
- `src/electron-api.d.ts` declares the `ElectronAPI` interface and augments global `Window`
- `src/preload/index.d.ts` declares the `ElectronAPI` interface and augments global `Window`
## Security
+5 -30
View File
@@ -5,44 +5,19 @@ import { resolve } from 'path'
export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()],
build: {
outDir: 'dist-electron',
rollupOptions: {
input: {
index: resolve(__dirname, 'electron/main.ts')
}
}
}
},
preload: {
plugins: [externalizeDepsPlugin()],
build: {
outDir: 'dist-electron',
rollupOptions: {
input: {
index: resolve(__dirname, 'electron/preload.ts')
}
}
}
},
renderer: {
root: 'src',
build: {
outDir: resolve(__dirname, 'dist-electron/renderer'),
rollupOptions: {
input: {
index: resolve(__dirname, 'src/index.html')
}
}
},
resolve: {
alias: {
'@renderer': resolve(__dirname, 'src')
}
'@renderer': resolve(__dirname, 'src/renderer/src'),
},
},
plugins: [vue()],
server: {
port: 5173
}
}
port: 5173,
},
},
})
+1 -1
View File
@@ -13,7 +13,7 @@ const commonLanguageOptions = {
}
export default tseslint.config(
{ ignores: ['dist', 'dist-electron', 'release', 'coverage', 'node_modules'] },
{ ignores: ['dist', 'out', 'release', 'coverage', 'node_modules'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.ts'],
+3 -4
View File
@@ -9,7 +9,7 @@
},
"homepage": "http://git.jokul.space/Jokul/JRedisDesktop",
"type": "module",
"main": "./dist-electron/main.js",
"main": "./out/main/index.js",
"allowScripts": {
"electron": true,
"esbuild": true,
@@ -60,10 +60,9 @@
"output": "release"
},
"files": [
"dist/**/*",
"dist-electron/**/*",
"out/**/*",
"!**/*.map",
"!dist-electron/**/*.map",
"!out/**/*.map",
"package.json"
],
"publish": {
+1 -1
View File
@@ -22,7 +22,7 @@ function createWindow(): void {
icon: nativeImage.createFromPath(iconPath),
backgroundColor: nativeTheme.shouldUseDarkColors ? '#0f0f1a' : '#f8fafc',
webPreferences: {
preload: join(__dirname, '../preload.js'),
preload: join(__dirname, '../preload/index.mjs'),
contextIsolation: true,
nodeIntegration: false,
sandbox: false,
View File
+1 -1
View File
@@ -7,6 +7,6 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="./main.ts"></script>
<script type="module" src="./src/main.ts"></script>
</body>
</html>
View File
+2 -2
View File
@@ -1,7 +1,7 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
{ "path": "./tsconfig.node.json" },
{ "path": "./tsconfig.web.json" }
]
}
+1 -1
View File
@@ -19,5 +19,5 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["electron.vite.config.ts", "electron"]
"include": ["electron.vite.config.ts", "src/main/**/*", "src/preload/**/*.ts"]
}
+8 -2
View File
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.web.tsbuildinfo",
"target": "es2023",
"lib": ["ESNext", "DOM"],
"module": "ESNext",
@@ -14,10 +14,16 @@
"moduleDetection": "force",
"noEmit": true,
/* Path alias */
"baseUrl": ".",
"paths": {
"@renderer/*": ["src/renderer/src/*"]
},
/* Linting */
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
"include": ["src/renderer/src/**/*", "src/preload/**/*.d.ts"]
}