6月4日 13:55

Electron调试指南:主进程、渲染进程和生产环境排查

Electron 有两个进程,调试方法完全不同:渲染进程用 Chrome DevTools,和调试网页一样;主进程是 Node.js 环境,需要用 VS Code 或远程调试协议。很多人只会开 DevTools,主进程出了问题只能 console.log 猜——这篇文章把两个进程的调试方法都讲清楚,以及生产环境下的排查手段。

渲染进程调试:DevTools

渲染进程就是 Chromium 的网页进程,调试体验和 Chrome 一样。

自动打开 DevTools

开发模式下自动打开,生产模式关闭:

javascript
mainWindow = 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

自定义快捷键切换

javascript
const { 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 里:

bash
npm install --save-dev electron-devtools-installer
javascript
const { 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 连接主进程:

javascript
app.commandLine.appendSwitch('remote-debugging-port', '9222')

启动应用后,在 Chrome 里打开 chrome://inspect,点击 "Configure..." 添加 localhost:9222,就能看到 Electron 主进程的 Node.js 上下文,可以直接断点调试。

也可以命令行启动:

bash
npx 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') 在主进程拦截所有消息:

javascript
mainWindow.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,需要靠日志:

日志收集

javascript
const { 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,自动捕获主进程和渲染进程的崩溃:

javascript
const Sentry = require('@sentry/electron') Sentry.init({ dsn: 'your-dsn', attachStacktrace: true, })

MiniDump 崩溃也能捕获——这是 DevTools 做不到的。

标签:Electron