Electron调试指南:主进程、渲染进程和生产环境排查
Electron 有两个进程,调试方法完全不同:渲染进程用 Chrome DevTools,和调试网页一样;主进程是 Node.js 环境,需要用 VS Code 或远程调试协议。很多人只会开 DevTools,主进程出了问题只能 console.log 猜——这篇文章把两个进程的调试方法都讲清楚,以及生产环境下的排查手段。
渲染进程调试:DevTools
渲染进程就是 Chromium 的网页进程,调试体验和 Chrome 一样。
自动打开 DevTools
开发模式下自动打开,生产模式关闭:
javascriptmainWindow = new BrowserWindow({ /* ... */ }) mainWindow.loadFile('index.html') if (process.env.NODE_ENV === 'development') { mainWindow.webContents.openDevTools() }
打包后的应用可以通过快捷键 Ctrl+Shift+I(Windows/Linux)或 Cmd+Option+I(macOS)手动打开。如果你不想让用户打开 DevTools,在创建窗口时设置 devTools: false。
自定义快捷键切换
javascriptconst { globalShortcut } = require('electron') app.whenReady().then(() => { globalShortcut.register('CommandOrControl+Shift+D', () => { const win = BrowserWindow.getFocusedWindow() if (!win) return win.webContents.isDevToolsOpened() ? win.webContents.closeDevTools() : win.webContents.openDevTools() }) }) app.on('will-quit', () => globalShortcut.unregisterAll())
安装框架 DevTools 扩展
React DevTools 和 Vue DevTools 可以直接集成到 Electron 里:
bashnpm install --save-dev electron-devtools-installer
javascriptconst { default: installExtension, REACT_DEVELOPER_TOOLS, VUEJS_DEVTOOLS } = require('electron-devtools-installer') app.whenReady().then(() => { installExtension(REACT_DEVELOPER_TOOLS) .then(name => console.log(`已安装: ${name}`)) .catch(err => console.error('安装失败:', err)) })
主进程调试:VS Code
主进程跑在 Node.js 里,DevTools 管不到。用 VS Code 断点调试是最方便的方式。
launch.json 配置
json{ "version": "0.2.0", "configurations": [ { "name": "Debug Main Process", "type": "node", "request": "launch", "cwd": "${workspaceFolder}", "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron", "windows": { "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd" }, "args": ["."], "outputCapture": "std" } ] }
F5 启动调试,在 main.js 里打断点,主进程代码可以逐行跟踪。注意:这只能调试主进程,渲染进程的断点要在 DevTools 里设。
同时调试两个进程
先启动主进程调试,然后在 DevTools 里调试渲染进程。两个调试器互不干扰。但要注意:主进程调试器会拦截 console.log,输出在 VS Code 的 Debug Console 而不是终端。
主进程调试:Chrome 远程调试
不想用 VS Code 的时候,可以用 Chrome 的 DevTools 连接主进程:
javascriptapp.commandLine.appendSwitch('remote-debugging-port', '9222')
启动应用后,在 Chrome 里打开 chrome://inspect,点击 "Configure..." 添加 localhost:9222,就能看到 Electron 主进程的 Node.js 上下文,可以直接断点调试。
也可以命令行启动:
bashnpx electron --remote-debugging-port=9222 .
远程调试的好处是不依赖 VS Code,任何能开 Chrome 的机器都能调试——适合远程排查 CI 环境或同事电脑上的问题。
IPC 调试
主进程和渲染进程通过 IPC 通信,消息传递出了问题最难排查——两边都能跑,但就是数据传不过去。
监听所有 IPC 消息
javascript// 主进程:监听所有来自渲染进程的消息 ipcMain.on('*', (event, ...args) => { console.log('[IPC Main ← Renderer]', event.channel, args) }) // 渲染进程(通过 preload):监听所有来自主进程的消息 contextBridge.exposeInMainWorld('electronAPI', { onMainMessage: (callback) => { ipcRenderer.on('*', (event, ...args) => { callback(event.channel, args) }) } })
实际上 Electron 的 ipcMain 不支持通配符监听,变通方案是用 webContents.on('ipc-message') 在主进程拦截所有消息:
javascriptmainWindow.webContents.on('ipc-message', (event, channel, ...args) => { console.log(`[IPC] ${channel}`, args) })
这样所有 ipcRenderer.send 的消息都能在主进程看到,不用在每个 handler 里加 log。
常见调试场景
白屏/加载失败
渲染进程白屏,先看 DevTools Console 有没有报错。如果连 DevTools 都打不开,可能是 HTML 文件路径错误或协议问题:
javascript// 错误:相对路径在打包后可能找不到文件 mainWindow.loadFile('index.html') // 正确:用 file:// 协议的绝对路径 mainWindow.loadFile(path.join(__dirname, 'index.html'))
内存泄漏
Electron 的内存泄漏通常来自两处:渲染进程的 JS 对象没释放(用 DevTools Memory 面板拍快照对比),或者主进程的 BrowserWindow 没 destroy()(检查窗口引用是否置 null)。
CPU 占用高
用 DevTools Performance 面板录制,看火焰图里的长任务。常见原因:渲染进程里的定时器没清理、大列表没虚拟化、主进程的同步文件操作阻塞了事件循环。
生产环境排查
生产环境没有 DevTools,需要靠日志:
日志收集
javascriptconst { dialog } = require('electron') const fs = require('fs') const log = require('electron-log') log.transports.file.resolvePath = () => path.join(app.getPath('userData'), 'logs/main.log') log.transports.file.maxSize = 5 * 1024 * 1024 // 5MB 轮转 // 捕获未处理的异常 process.on('uncaughtException', (error) => { log.error('Uncaught Exception:', error) dialog.showErrorBox('意外错误', error.message) })
electron-log 同时写文件和控制台,打包后日志在 userData/logs/ 目录下。用户反馈问题时让他们发这个文件。
远程错误上报
Sentry 提供 Electron SDK,自动捕获主进程和渲染进程的崩溃:
javascriptconst Sentry = require('@sentry/electron') Sentry.init({ dsn: 'your-dsn', attachStacktrace: true, })
MiniDump 崩溃也能捕获——这是 DevTools 做不到的。