调试技巧 #
一、调试概述 #
1.1 调试环境 #
text
┌─────────────────────────────────────────────────────────────┐
│ Electron 调试 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 主进程 │ │ 渲染进程 │ │
│ │ │ │ │ │
│ │ VS Code 调试 │ │ Chrome DevTools│ │
│ │ Node.js 调试 │ │ 控制台日志 │ │
│ │ console.log │ │ 断点调试 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ IPC 通信调试 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
1.2 调试工具 #
| 工具 | 用途 | 适用进程 |
|---|---|---|
| VS Code 调试器 | 断点、变量查看 | 主进程 |
| Chrome DevTools | DOM、网络、性能 | 渲染进程 |
| console.log | 简单日志 | 所有进程 |
| electron-log | 日志记录 | 所有进程 |
二、主进程调试 #
2.1 VS Code 调试配置 #
json
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Electron: Main Process",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
"args": ["."],
"outputCapture": "std",
"env": {
"NODE_ENV": "development"
}
},
{
"name": "Electron: Main Process (Attach)",
"type": "node",
"request": "attach",
"port": 5858,
"address": "localhost"
}
]
}
2.2 命令行调试 #
bash
# 启动调试模式
electron . --inspect=5858
# 等待调试器连接
electron . --inspect-brk=5858
# 然后在 Chrome 中打开
# chrome://inspect
2.3 使用 console.log #
javascript
// main.js
console.log('主进程日志');
console.log('变量值:', someVariable);
console.error('错误信息:', error);
console.time('操作耗时');
// ... 操作
console.timeEnd('操作耗时');
2.4 使用 electron-log #
bash
npm install electron-log
javascript
// main.js
const log = require('electron-log');
log.info('信息日志');
log.warn('警告日志');
log.error('错误日志');
// 设置日志文件
log.transports.file.resolvePath = () => path.join(app.getPath('userData'), 'logs/main.log');
三、渲染进程调试 #
3.1 打开 DevTools #
javascript
// 在主进程中打开
mainWindow.webContents.openDevTools();
// 条件打开
if (isDev) {
mainWindow.webContents.openDevTools();
}
// 分离窗口
mainWindow.webContents.openDevTools({ mode: 'detach' });
3.2 DevTools 功能 #
javascript
// 控制台
console.log('渲染进程日志');
console.table([{ name: 'John', age: 30 }]);
// 断点
debugger;
// 性能分析
console.time('render');
renderList();
console.timeEnd('render');
// 内存快照
// DevTools -> Memory -> Take heap snapshot
3.3 Vue/React DevTools #
javascript
// 安装 Vue DevTools
// npm install @vue/devtools --save-dev
// 安装 React DevTools
// npm install react-devtools --save-dev
// 在主进程中加载扩展
const { session } = require('electron');
const path = require('path');
app.whenReady().then(() => {
session.defaultSession.loadExtension(
path.join(__dirname, 'extensions/vue-devtools')
);
});
3.4 渲染进程日志 #
javascript
// renderer.js
const originalConsole = { ...console };
console.log = (...args) => {
originalConsole.log('[Renderer]', ...args);
// 可选:发送到主进程
ipcRenderer.send('log', { type: 'log', args });
};
四、IPC 调试 #
4.1 IPC 日志中间件 #
javascript
// main.js
const originalOn = ipcMain.on.bind(ipcMain);
const originalHandle = ipcMain.handle.bind(ipcMain);
ipcMain.on = (channel, listener) => {
const wrappedListener = (event, ...args) => {
console.log(`[IPC] 收到: ${channel}`, args);
listener(event, ...args);
};
originalOn(channel, wrappedListener);
};
ipcMain.handle = (channel, listener) => {
const wrappedListener = async (event, ...args) => {
console.log(`[IPC] 处理: ${channel}`, args);
const start = Date.now();
const result = await listener(event, ...args);
console.log(`[IPC] 完成: ${channel} (${Date.now() - start}ms)`);
return result;
};
originalHandle(channel, wrappedListener);
};
4.2 渲染进程 IPC 日志 #
javascript
// renderer.js
const originalSend = ipcRenderer.send.bind(ipcRenderer);
const originalInvoke = ipcRenderer.invoke.bind(ipcRenderer);
ipcRenderer.send = (channel, ...args) => {
console.log(`[IPC] 发送: ${channel}`, args);
originalSend(channel, ...args);
};
ipcRenderer.invoke = async (channel, ...args) => {
console.log(`[IPC] 调用: ${channel}`, args);
const start = Date.now();
const result = await originalInvoke(channel, ...args);
console.log(`[IPC] 结果: ${channel} (${Date.now() - start}ms)`);
return result;
};
五、性能分析 #
5.1 主进程性能 #
javascript
// 使用 Node.js 性能钩子
const { performance, PerformanceObserver } = require('perf_hooks');
const obs = new PerformanceObserver((list) => {
const entries = list.getEntries();
entries.forEach((entry) => {
console.log(`${entry.name}: ${entry.duration}ms`);
});
});
obs.observe({ entryTypes: ['measure'] });
performance.mark('start');
// ... 操作
performance.mark('end');
performance.measure('操作耗时', 'start', 'end');
5.2 渲染进程性能 #
javascript
// 使用 Performance API
performance.mark('start-render');
renderList();
performance.mark('end-render');
performance.measure('render', 'start-render', 'end-render');
const measures = performance.getEntriesByName('render');
console.log(measures[0].duration);
5.3 内存分析 #
javascript
// 主进程内存
const used = process.memoryUsage();
console.log({
rss: `${used.rss / 1024 / 1024} MB`,
heapTotal: `${used.heapTotal / 1024 / 1024} MB`,
heapUsed: `${used.heapUsed / 1024 / 1024} MB`
});
// 渲染进程内存
// DevTools -> Memory -> Take heap snapshot
5.4 CPU 分析 #
javascript
// 主进程 CPU 分析
const { writeFileSync } = require('fs');
if (isDev) {
const profiler = require('v8-profiler-next');
profiler.startProfiling('CPU Profile');
setTimeout(() => {
const profile = profiler.stopProfiling('CPU Profile');
profile.export((error, result) => {
writeFileSync('profile.cpuprofile', result);
profile.delete();
});
}, 10000);
}
六、错误处理 #
6.1 全局错误捕获 #
javascript
// 主进程
process.on('uncaughtException', (error) => {
console.error('未捕获异常:', error);
// 记录日志
log.error('Uncaught Exception:', error);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('未处理的 Promise 拒绝:', reason);
});
// 渲染进程
window.addEventListener('error', (event) => {
console.error('渲染进程错误:', event.error);
});
window.addEventListener('unhandledrejection', (event) => {
console.error('未处理的 Promise 拒绝:', event.reason);
});
6.2 错误上报 #
javascript
// 错误上报服务
async function reportError(error, context = {}) {
try {
await fetch('https://error-tracking.example.com/api/report', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
error: {
message: error.message,
stack: error.stack
},
context,
timestamp: new Date().toISOString(),
platform: process.platform,
version: app.getVersion()
})
});
} catch (e) {
console.error('错误上报失败:', e);
}
}
七、常见问题排查 #
7.1 白屏问题 #
javascript
// 检查加载状态
mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => {
console.error('页面加载失败:', errorCode, errorDescription);
});
mainWindow.webContents.on('did-finish-load', () => {
console.log('页面加载完成');
});
// 检查控制台错误
mainWindow.webContents.on('console-message', (event, level, message, line, sourceId) => {
console.log('控制台消息:', message);
});
7.2 IPC 通信问题 #
javascript
// 检查 IPC 通道
ipcMain.on('debug-channels', () => {
console.log('已注册的 IPC 处理器:', ipcMain.eventNames());
});
// 检查消息格式
ipcMain.handle('debug-message', (event, data) => {
console.log('收到消息:', JSON.stringify(data, null, 2));
return { received: true };
});
7.3 内存泄漏 #
javascript
// 定期检查内存
setInterval(() => {
const used = process.memoryUsage();
console.log('内存使用:', used);
// 触发垃圾回收(需要 --expose-gc 标志)
if (global.gc) {
global.gc();
}
}, 60000);
7.4 窗口问题 #
javascript
// 窗口状态调试
mainWindow.on('ready-to-show', () => {
console.log('窗口准备显示');
});
mainWindow.on('show', () => {
console.log('窗口显示');
});
mainWindow.on('hide', () => {
console.log('窗口隐藏');
});
mainWindow.on('close', (event) => {
console.log('窗口关闭');
});
八、调试工具 #
8.1 Electron Fiddle #
text
Electron Fiddle 是官方提供的快速原型工具
可以快速测试 Electron 代码片段
下载地址: https://www.electronjs.org/fiddle
8.2 开发者工具扩展 #
javascript
// 加载开发者工具扩展
const { session } = require('electron');
const path = require('path');
app.whenReady().then(() => {
// React DevTools
session.defaultSession.loadExtension(
path.join(__dirname, 'extensions/react-devtools')
);
// Vue DevTools
session.defaultSession.loadExtension(
path.join(__dirname, 'extensions/vue-devtools')
);
});
8.3 日志查看器 #
javascript
// 创建日志查看窗口
function openLogViewer() {
const logWin = new BrowserWindow({
width: 800,
height: 600,
title: '日志查看器'
});
logWin.loadFile('log-viewer.html');
}
九、最佳实践 #
9.1 调试检查清单 #
markdown
- [ ] 启用开发者工具
- [ ] 配置 VS Code 调试
- [ ] 添加错误处理
- [ ] 记录关键日志
- [ ] 监控内存使用
- [ ] 检查 IPC 通信
- [ ] 分析性能瓶颈
9.2 生产环境调试 #
javascript
// 生产环境调试开关
const DEBUG_MODE = process.env.ELECTRON_DEBUG === 'true';
if (DEBUG_MODE) {
mainWindow.webContents.openDevTools();
// 启用详细日志
}
十、总结 #
10.1 核心要点 #
| 要点 | 说明 |
|---|---|
| 主进程调试 | VS Code 调试器 |
| 渲染进程调试 | Chrome DevTools |
| IPC 调试 | 日志中间件 |
| 性能分析 | Performance API |
| 错误处理 | 全局错误捕获 |
10.2 下一步 #
现在你已经掌握了调试技巧,接下来让我们学习 打包配置,深入了解 Electron 应用的打包和分发!
最后更新:2026-03-28