Loading...
Loading...
Compare original and translation side by side
How to structure the app?
│
├─ **Security First (Recommended)**
│ ├─ Context Isolation? → **Yes** (Standard since v12)
│ ├─ Node Integration? → **No** (Never in Renderer)
│ └─ Preload Scripts? → **Yes** (Bridge API)
│
├─ **Data Persistence**
│ ├─ Simple Settings? → **electron-store** (JSON)
│ ├─ Large Datasets? → **SQLite** (`better-sqlite3` in Main process)
│ └─ User Files? → **Native File System API**
│
└─ **UI Framework**
├─ React/Vue/Svelte? → **Yes** (Standard SPA approach)
├─ Multiple Windows? → **Window Manager Pattern**
└─ System Tray App? → **Hidden Window Pattern**如何构建应用架构?
│
├─ **安全优先(推荐)**
│ ├─ 上下文隔离? → **是**(v12版本起的标准配置)
│ ├─ Node集成? → **否**(绝对不要在渲染进程中启用)
│ └─ 预加载脚本? → **是**(桥接API)
│
├─ **数据持久化**
│ ├─ 简单设置? → **electron-store**(JSON格式)
│ ├─ 大型数据集? → **SQLite**(在主进程中使用`better-sqlite3`)
│ └─ 用户文件? → **原生文件系统API**
│
└─ **UI框架**
├─ React/Vue/Svelte? → **是**(标准SPA开发方式)
├─ 多窗口? → **窗口管理器模式**
└─ 系统托盘应用? → **隐藏窗口模式**| Pattern | Method | Use Case |
|---|---|---|
| One-Way (Renderer → Main) | | logging, analytics, minimizing window |
| Two-Way (Request/Response) | | DB queries, file reads, heavy computations |
| Main → Renderer | | Menu actions, system events, push notifications |
security-auditornodeIntegration: truecontextIsolationhttps://remote| 模式 | 方法 | 适用场景 |
|---|---|---|
| 单向(渲染进程→主进程) | | 日志记录、数据分析、窗口最小化 |
| 双向(请求/响应) | | 数据库查询、文件读取、密集型计算 |
| 主进程→渲染进程 | | 菜单操作、系统事件、推送通知 |
security-auditornodeIntegration: truecontextIsolationhttps://remoteelectron-linkv8-compile-cacherequire()main.ts// Bad
import { heavyLib } from 'heavy-lib';
// Good
ipcMain.handle('do-work', () => {
const heavyLib = require('heavy-lib');
heavyLib.process();
});esbuildwebpackelectron-linkv8-compile-cachemain.tsrequire()// 错误示例
import { heavyLib } from 'heavy-lib';
// 正确示例
ipcMain.handle('do-work', () => {
const heavyLib = require('heavy-lib');
heavyLib.process();
});esbuildwebpack// main.ts
import { Worker } from 'worker_threads';
ipcMain.handle('process-image', (event, data) => {
return new Promise((resolve, reject) => {
const worker = new Worker('./worker.js', { workerData: data });
worker.on('message', resolve);
worker.on('error', reject);
});
});// main.ts
import { Worker } from 'worker_threads';
ipcMain.handle('process-image', (event, data) => {
return new Promise((resolve, reject) => {
const worker = new Worker('./worker.js', { workerData: data });
worker.on('message', resolve);
worker.on('error', reject);
});
});myapp://open?id=123// main.ts
if (process.defaultApp) {
if (process.argv.length >= 2) {
app.setAsDefaultProtocolClient('myapp', process.execPath, [path.resolve(process.argv[1])]);
}
} else {
app.setAsDefaultProtocolClient('myapp');
}
app.on('open-url', (event, url) => {
event.preventDefault();
// Parse url 'myapp://...' and navigate renderer
mainWindow.webContents.send('navigate', url);
});myapp://open?id=123// main.ts
if (process.defaultApp) {
if (process.argv.length >= 2) {
app.setAsDefaultProtocolClient('myapp', process.execPath, [path.resolve(process.argv[1])]);
}
} else {
app.setAsDefaultProtocolClient('myapp');
}
app.on('open-url', (event, url) => {
event.preventDefault();
// 解析URL 'myapp://...' 并通知渲染进程导航
mainWindow.webContents.send('navigate', url);
});app-region: dragapp-region: drag