直接跳到内容

Electron 调试

调试概述

Electron 调试是一个多层次、多进程的复杂过程,涉及主进程渲染进程预加载脚本原生模块等多个执行环境。与传统的 Web 应用调试不同,Electron 应用需要同时处理 Node.js 运行时和 Chromium 渲染引擎的调试需求,这要求开发者掌握跨环境调试技术。

Electron 的特殊架构决定了其调试工作的分布性:

主进程调试 (Node.js 环境)

    | IPC 通信跟踪

渲染进程调试 (Chromium DevTools)

预加载脚本调试 (上下文隔离)

原生模块调试 (Native Addons)

有效的 Electron 调试需要在这些不同层面都具备相应的工具和技术支持。

开发工具配置

开发环境搭建

配置合适的开发环境是高效调试的基础,需要集成代码编辑器、终端和调试工具。

javascript
// package.json - 开发脚本配置
{
  "name": "electron-app",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "start": "electron .",
    "dev": "NODE_ENV=development electron .",
    "debug": "electron --inspect=9222 .",
    "debug-brk": "electron --inspect-brk=9222 .",
    "devtools": "electron --remote-debugging-port=8315 .",
    "test": "NODE_ENV=test electron ."
  },
  "devDependencies": {
    "electron": "^22.0.0",
    "electron-builder": "^23.6.0"
  }
}

环境变量配置

通过环境变量控制调试行为,实现开发和生产环境的差异化配置。

javascript
// config/debug-config.js
import { app } from 'electron';

class DebugConfig {
  constructor() {
    this.isDevelopment = process.env.NODE_ENV === 'development';
    this.isDebug = process.env.DEBUG === 'true';
    this.isTest = process.env.NODE_ENV === 'test';
  }

  getDebugOptions() {
    const baseOptions = {
      enableDevTools: this.isDevelopment || this.isDebug,
      enableReload: this.isDevelopment,
      enableLogging: this.isDevelopment || this.isDebug,
      enablePerformanceMonitor: this.isDevelopment
    };

    // 开发环境特定的调试选项
    if (this.isDevelopment) {
      return {
        ...baseOptions,
        devToolsMode: 'detach',
        consoleLevel: 'verbose',
        nodeIntegrationInWorker: true
      };
    }

    return baseOptions;
  }

  setupEnvironment() {
    if (this.isDevelopment) {
      // 设置开发环境变量
      process.env.ELECTRON_IS_DEV = '1';
      process.env.ELECTRON_DEBUG = 'true';
      
      // 启用更详细的日志
      process.env.DEBUG = 'electron*,node*';
      
      // 禁用硬件加速以提高调试性能
      app.disableHardwareAcceleration();
    }
  }
}

export default DebugConfig;

主进程调试

命令行调试

使用 Node.js 内置的调试器通过命令行参数启动 Electron 主进程调试。

bash
# 启动调试,在9222端口监听
electron --inspect=9222 .

# 启动调试并在第一行中断
electron --inspect-brk=9222 .

# 指定IP地址进行远程调试
electron --inspect=0.0.0.0:9222 .

# 启用远程调试
electron --remote-debugging-port=8315 .

Chrome DevTools 连接

通过 Chrome 浏览器连接到 Electron 主进程进行调试。

javascript
// 在 Chrome 地址栏输入:
chrome://inspect

// 配置发现目标
// 添加 localhost:9222 到 Target discovery settings

调试界面示意图:

Chrome DevTools
    |
    | 连接到 localhost:9222
    |
Electron 主进程
    ├── Sources (源代码调试)
    ├── Console (控制台输出)
    ├── Memory (内存分析)
    └── Performance (性能分析)

VS Code 调试配置

配置 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": [
        ".",
        "--remote-debugging-port=9223"
      ],
      "env": {
        "NODE_ENV": "development",
        "ELECTRON_IS_DEV": "1"
      },
      "console": "integratedTerminal",
      "protocol": "inspector",
      "sourceMaps": true,
      "timeout": 20000
    },
    {
      "name": "Attach to Main Process",
      "type": "node",
      "request": "attach",
      "port": 9222,
      "timeout": 20000,
      "localRoot": "${workspaceFolder}",
      "remoteRoot": ".",
      "sourceMaps": true
    },
    {
      "name": "Debug Renderer Process",
      "type": "chrome",
      "request": "attach",
      "port": 9223,
      "webRoot": "${workspaceFolder}/src",
      "sourceMaps": true,
      "timeout": 20000
    }
  ],
  "compounds": [
    {
      "name": "Debug All",
      "configurations": [
        "Debug Main Process",
        "Debug Renderer Process"
      ],
      "stopAll": true
    }
  ]
}

程序化调试控制

在代码中动态控制调试行为,实现条件断点和调试输出。

javascript
// debug/main-process-debug.js
import { app, BrowserWindow } from 'electron';
import util from 'util';

class MainProcessDebug {
  constructor() {
    this.debugEnabled = process.env.NODE_ENV === 'development';
    this.breakpoints = new Map();
  }

  // 条件调试输出
  debugLog(message, ...args) {
    if (this.debugEnabled) {
      const timestamp = new Date().toISOString();
      const formattedMessage = util.format(message, ...args);
      console.log(`[MAIN ${timestamp}] ${formattedMessage}`);
    }
  }

  // 内存使用监控
  logMemoryUsage(context = '') {
    if (this.debugEnabled) {
      const memoryUsage = process.memoryUsage();
      this.debugLog('Memory Usage %s:', context, {
        rss: `${(memoryUsage.rss / 1024 / 1024).toFixed(2)} MB`,
        heapTotal: `${(memoryUsage.heapTotal / 1024 / 1024).toFixed(2)} MB`,
        heapUsed: `${(memoryUsage.heapUsed / 1024 / 1024).toFixed(2)} MB`,
        external: `${(memoryUsage.external / 1024 / 1024).toFixed(2)} MB`
      });
    }
  }

  // 进程信息监控
  logProcessInfo() {
    if (this.debugEnabled) {
      this.debugLog('Process Info:', {
        pid: process.pid,
        platform: process.platform,
        arch: process.arch,
        version: process.version,
        electronVersion: process.versions.electron,
        chromeVersion: process.versions.chrome
      });
    }
  }

  // IPC 通信跟踪
  setupIPCDebugging(ipcMain) {
    if (!this.debugEnabled) return;

    const originalHandle = ipcMain.handle;
    ipcMain.handle = function(channel, listener) {
      return originalHandle.call(ipcMain, channel, async (event, ...args) => {
        console.log(`[IPC →] ${channel}`, args);
        const startTime = Date.now();
        
        try {
          const result = await listener(event, ...args);
          const duration = Date.now() - startTime;
          console.log(`[IPC ←] ${channel} (${duration}ms)`, result);
          return result;
        } catch (error) {
          const duration = Date.now() - startTime;
          console.error(`[IPC ✗] ${channel} (${duration}ms)`, error);
          throw error;
        }
      });
    };
  }

  // 窗口创建调试
  debugWindowCreation(window, options) {
    if (!this.debugEnabled) return;

    this.debugLog('Creating window:', {
      id: window.id,
      options: {
        width: options.width,
        height: options.height,
        webPreferences: {
          nodeIntegration: options.webPreferences?.nodeIntegration,
          contextIsolation: options.webPreferences?.contextIsolation,
          enableRemoteModule: options.webPreferences?.enableRemoteModule
        }
      }
    });

    // 监听窗口事件
    window.on('ready-to-show', () => {
      this.debugLog('Window ready to show:', { id: window.id });
    });

    window.on('closed', () => {
      this.debugLog('Window closed:', { id: window.id });
    });

    window.webContents.on('did-finish-load', () => {
      this.debugLog('Window finished loading:', { id: window.id });
    });
  }
}

export default MainProcessDebug;

渲染进程调试

开发者工具集成

在渲染进程中集成开发者工具,支持动态打开和配置。

javascript
// debug/renderer-debug.js
class RendererDebug {
  constructor() {
    this.isDevelopment = process.env.NODE_ENV === 'development';
    this.devToolsOpened = false;
    this.consoleHistory = [];
  }

  // 初始化渲染进程调试
  initialize() {
    if (!this.isDevelopment) return;

    this.setupConsoleOverride();
    this.setupErrorHandling();
    this.injectDebugHelpers();
  }

  // 打开开发者工具
  openDevTools() {
    if (this.isDevelopment && !this.devToolsOpened) {
      try {
        const { remote } = require('electron');
        const currentWindow = remote.getCurrentWindow();
        currentWindow.webContents.openDevTools({ mode: 'detach' });
        this.devToolsOpened = true;
        
        console.debug('开发者工具已打开');
      } catch (error) {
        console.warn('无法打开开发者工具:', error);
      }
    }
  }

  // 重写 console 方法进行增强
  setupConsoleOverride() {
    const originalConsole = {
      log: console.log,
      error: console.error,
      warn: console.warn,
      info: console.info,
      debug: console.debug
    };

    // 重写 console.log
    console.log = (...args) => {
      this.consoleHistory.push({
        type: 'log',
        timestamp: new Date().toISOString(),
        args: args.map(arg => this.safeStringify(arg))
      });
      originalConsole.log(...args);
    };

    // 重写 console.error
    console.error = (...args) => {
      this.consoleHistory.push({
        type: 'error',
        timestamp: new Date().toISOString(),
        args: args.map(arg => this.safeStringify(arg))
      });
      originalConsole.error(...args);
    };

    // 保存原始方法供外部访问
    window.originalConsole = originalConsole;
  }

  // 安全序列化对象
  safeStringify(obj) {
    try {
      if (typeof obj === 'object' && obj !== null) {
        return JSON.stringify(obj, (key, value) => {
          // 处理循环引用
          if (typeof value === 'object' && value !== null) {
            if (key && value.constructor.name === 'Window') {
              return '[Window]';
            }
            if (key && value.constructor.name === 'Document') {
              return '[Document]';
            }
          }
          return value;
        });
      }
      return String(obj);
    } catch (error) {
      return `[Unserializable: ${error.message}]`;
    }
  }

  // 设置错误处理
  setupErrorHandling() {
    window.addEventListener('error', (event) => {
      console.error('全局错误:', event.error);
      this.logErrorToServer(event.error);
    });

    window.addEventListener('unhandledrejection', (event) => {
      console.error('未处理的 Promise 拒绝:', event.reason);
      this.logErrorToServer(event.reason);
    });

    // 重写 window.onerror
    const originalOnError = window.onerror;
    window.onerror = (message, source, lineno, colno, error) => {
      console.error('窗口错误:', {
        message, source, lineno, colno, error
      });
      
      if (originalOnError) {
        return originalOnError.call(window, message, source, lineno, colno, error);
      }
      return false;
    };
  }

  // 注入调试辅助函数
  injectDebugHelpers() {
    // 全局调试对象
    window.__DEBUG__ = {
      // 获取控制台历史
      getConsoleHistory: () => [...this.consoleHistory],
      
      // 清空控制台历史
      clearConsoleHistory: () => {
        this.consoleHistory = [];
      },
      
      // 性能测量工具
      measure: (name, fn) => {
        const start = performance.now();
        const result = fn();
        const end = performance.now();
        console.log(`⏱️ ${name}: ${(end - start).toFixed(2)}ms`);
        return result;
      },
      
      // 内存快照
      memorySnapshot: () => {
        if (performance.memory) {
          const memory = performance.memory;
          return {
            used: `${(memory.usedJSHeapSize / 1048576).toFixed(2)} MB`,
            total: `${(memory.totalJSHeapSize / 1048576).toFixed(2)} MB`,
            limit: `${(memory.jsHeapSizeLimit / 1048576).toFixed(2)} MB`
          };
        }
        return '内存信息不可用';
      },
      
      // DOM 元素统计
      domStats: () => {
        return {
          elements: document.getElementsByTagName('*').length,
          nodes: document.querySelectorAll('*').length,
          memory: window.performance.memory
        };
      }
    };

    // 添加键盘快捷键
    document.addEventListener('keydown', (event) => {
      // Ctrl+Shift+I 打开开发者工具
      if (event.ctrlKey && event.shiftKey && event.key === 'I') {
        event.preventDefault();
        this.openDevTools();
      }
      
      // Ctrl+Shift+L 清空控制台
      if (event.ctrlKey && event.shiftKey && event.key === 'L') {
        event.preventDefault();
        console.clear();
      }
    });
  }

  // 记录错误到服务器(开发环境)
  logErrorToServer(error) {
    if (!this.isDevelopment) return;

    const errorInfo = {
      message: error.message,
      stack: error.stack,
      timestamp: new Date().toISOString(),
      url: window.location.href,
      userAgent: navigator.userAgent
    };

    // 在实际应用中,这里可以发送到错误收集服务
    console.error('错误信息:', errorInfo);
  }
}

export default RendererDebug;

渲染进程调试集成

在主窗口中集成渲染进程调试功能。

javascript
// main.js - 渲染进程调试集成
import { app, BrowserWindow } from 'electron';
import MainProcessDebug from './debug/main-process-debug.js';

const mainDebug = new MainProcessDebug();

function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      enableRemoteModule: false,
      preload: path.join(__dirname, 'preload.js'),
      // 开发环境启用调试功能
      devTools: mainDebug.debugEnabled,
      webSecurity: !mainDebug.debugEnabled // 开发环境禁用web安全以方便调试
    }
  });

  // 调试窗口创建
  mainDebug.debugWindowCreation(mainWindow, {
    width: 1200,
    height: 800,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true
    }
  });

  // 开发环境自动打开开发者工具
  if (mainDebug.debugEnabled) {
    mainWindow.webContents.openDevTools({ mode: 'detach' });
    
    // 监听开发者工具事件
    mainWindow.webContents.on('devtools-opened', () => {
      mainDebug.debugLog('开发者工具已打开');
    });
    
    mainWindow.webContents.on('devtools-closed', () => {
      mainDebug.debugLog('开发者工具已关闭');
    });
  }

  mainWindow.loadFile('index.html');
}

app.whenReady().then(() => {
  mainDebug.setupEnvironment();
  mainDebug.logProcessInfo();
  createWindow();
});

预加载脚本调试

上下文隔离调试

预加载脚本运行在特殊的上下文中,需要特定的调试技术。

javascript
// preload.js - 预加载脚本调试
import { contextBridge, ipcRenderer } from 'electron';

class PreloadDebug {
  constructor() {
    this.isDevelopment = process.env.NODE_ENV === 'development';
    this.initialize();
  }

  initialize() {
    if (this.isDevelopment) {
      this.setupPreloadDebugging();
    }
  }

  setupPreloadDebugging() {
    // 预加载脚本特定的控制台输出
    const originalLog = console.log;
    console.log = (...args) => {
      originalLog('[PRELOAD]', ...args);
    };

    // IPC 通信调试
    this.debugIPC();
    
    // 错误处理
    this.setupErrorHandling();
  }

  debugIPC() {
    const originalInvoke = ipcRenderer.invoke;
    ipcRenderer.invoke = (channel, ...args) => {
      console.log(`[IPC → PRELOAD] ${channel}`, args);
      return originalInvoke.call(ipcRenderer, channel, ...args)
        .then(result => {
          console.log(`[IPC ← PRELOAD] ${channel}`, result);
          return result;
        })
        .catch(error => {
          console.error(`[IPC ✗ PRELOAD] ${channel}`, error);
          throw error;
        });
    };

    // 调试事件监听器
    const originalOn = ipcRenderer.on;
    ipcRenderer.on = (channel, listener) => {
      console.log(`[IPC ☁ PRELOAD] 监听 ${channel}`);
      return originalOn.call(ipcRenderer, channel, (event, ...args) => {
        console.log(`[IPC ← PRELOAD] ${channel}`, args);
        return listener(event, ...args);
      });
    };
  }

  setupErrorHandling() {
    window.addEventListener('error', (event) => {
      console.error('[PRELOAD ERROR]', event.error);
    });

    // 暴露调试工具到渲染进程
    contextBridge.exposeInMainWorld('preloadDebug', {
      getPreloadInfo: () => ({
        isDevelopment: this.isDevelopment,
        nodeVersion: process.versions.node,
        electronVersion: process.versions.electron,
        chromeVersion: process.versions.chrome
      }),
      testIPC: () => {
        return ipcRenderer.invoke('debug-test', { test: 'preload-debug' });
      }
    });
  }
}

// 初始化预加载调试
new PreloadDebug();

// 暴露安全的 API 到渲染进程
contextBridge.exposeInMainWorld('electronAPI', {
  // 正常的 API 暴露...
  openFile: () => ipcRenderer.invoke('dialog:openFile'),
  // ... 其他 API
});

性能调试与分析

性能监控集成

集成性能监控工具,分析应用性能瓶颈。

javascript
// debug/performance-debug.js
class PerformanceDebug {
  constructor() {
    this.metrics = new Map();
    this.performanceEntries = [];
    this.enabled = process.env.NODE_ENV === 'development';
  }

  // 开始性能测量
  startMeasure(name) {
    if (!this.enabled) return;

    this.metrics.set(name, {
      startTime: performance.now(),
      startMemory: this.getMemoryUsage(),
      startHrtime: process.hrtime()
    });
  }

  // 结束性能测量
  endMeasure(name, context = {}) {
    if (!this.enabled || !this.metrics.has(name)) return;

    const metric = this.metrics.get(name);
    const endTime = performance.now();
    const duration = endTime - metric.startTime;
    const memoryDiff = this.getMemoryUsage();

    const performanceEntry = {
      name,
      duration,
      context,
      memory: {
        rss: memoryDiff.rss - metric.startMemory.rss,
        heapUsed: memoryDiff.heapUsed - metric.startMemory.heapUsed,
        heapTotal: memoryDiff.heapTotal - metric.startMemory.heapTotal
      },
      timestamp: new Date().toISOString()
    };

    this.performanceEntries.push(performanceEntry);
    
    console.log(`📊 性能测量 ${name}:`, {
      时长: `${duration.toFixed(2)}ms`,
      内存变化: `${((memoryDiff.heapUsed - metric.startMemory.heapUsed) / 1024 / 1024).toFixed(2)} MB`,
      上下文: context
    });

    this.metrics.delete(name);
    return performanceEntry;
  }

  // 获取内存使用情况
  getMemoryUsage() {
    if (process.memoryUsage) {
      return process.memoryUsage();
    }
    return { rss: 0, heapTotal: 0, heapUsed: 0, external: 0 };
  }

  // 自动测量函数性能
  async measureFunction(name, fn, context = {}) {
    this.startMeasure(name);
    
    try {
      const result = await fn();
      this.endMeasure(name, { ...context, success: true });
      return result;
    } catch (error) {
      this.endMeasure(name, { ...context, success: false, error: error.message });
      throw error;
    }
  }

  // 获取性能报告
  getPerformanceReport() {
    const entries = this.performanceEntries;
    const totalDuration = entries.reduce((sum, entry) => sum + entry.duration, 0);
    const averageDuration = totalDuration / entries.length;
    
    const slowest = entries.reduce((slowest, entry) => 
      entry.duration > slowest.duration ? entry : slowest, { duration: 0 }
    );
    
    const fastest = entries.reduce((fastest, entry) => 
      entry.duration < fastest.duration ? entry : fastest, { duration: Infinity }
    );

    return {
      summary: {
        totalEntries: entries.length,
        totalDuration: `${totalDuration.toFixed(2)}ms`,
        averageDuration: `${averageDuration.toFixed(2)}ms`,
        slowestOperation: slowest.name,
        slowestDuration: `${slowest.duration.toFixed(2)}ms`,
        fastestOperation: fastest.name,
        fastestDuration: `${fastest.duration.toFixed(2)}ms`
      },
      entries: entries
    };
  }

  // 重置性能数据
  reset() {
    this.metrics.clear();
    this.performanceEntries = [];
  }

  // 导出性能数据
  exportData() {
    return {
      report: this.getPerformanceReport(),
      rawEntries: this.performanceEntries
    };
  }
}

export default PerformanceDebug;

内存泄漏检测

集成内存泄漏检测工具,识别和解决内存问题。

javascript
// debug/memory-debug.js
class MemoryDebug {
  constructor() {
    this.snapshots = new Map();
    this.leakDetectionEnabled = process.env.NODE_ENV === 'development';
  }

  // 创建内存快照
  takeSnapshot(name) {
    if (!this.leakDetectionEnabled) return null;

    if (global.gc) {
      global.gc(); // 强制垃圾回收(需要 --expose-gc 参数)
    }

    const snapshot = {
      name,
      timestamp: new Date().toISOString(),
      memory: process.memoryUsage(),
      heapSnapshot: this.getHeapInfo()
    };

    this.snapshots.set(name, snapshot);
    console.log(`📸 内存快照 ${name}:`, snapshot.memory);
    
    return snapshot;
  }

  // 获取堆信息
  getHeapInfo() {
    const memory = process.memoryUsage();
    return {
      heapUsed: `${(memory.heapUsed / 1024 / 1024).toFixed(2)} MB`,
      heapTotal: `${(memory.heapTotal / 1024 / 1024).toFixed(2)} MB`,
      rss: `${(memory.rss / 1024 / 1024).toFixed(2)} MB`
    };
  }

  // 比较快照检测内存泄漏
  compareSnapshots(snapshot1Name, snapshot2Name) {
    const snapshot1 = this.snapshots.get(snapshot1Name);
    const snapshot2 = this.snapshots.get(snapshot2Name);

    if (!snapshot1 || !snapshot2) {
      console.warn('快照不存在');
      return null;
    }

    const memory1 = snapshot1.memory;
    const memory2 = snapshot2.memory;

    const diff = {
      heapUsed: memory2.heapUsed - memory1.heapUsed,
      heapTotal: memory2.heapTotal - memory1.heapTotal,
      rss: memory2.rss - memory1.rss,
      external: memory2.external - memory1.external
    };

    const leaksDetected = diff.heapUsed > 5 * 1024 * 1024; // 5MB 阈值

    console.log(`🔍 内存比较 ${snapshot1Name} → ${snapshot2Name}:`, {
      堆使用变化: `${(diff.heapUsed / 1024 / 1024).toFixed(2)} MB`,
      堆总量变化: `${(diff.heapTotal / 1024 / 1024).toFixed(2)} MB`,
      RSS变化: `${(diff.rss / 1024 / 1024).toFixed(2)} MB`,
      检测到泄漏: leaksDetected ? '⚠️ 是' : '✅ 否'
    });

    return {
      diff,
      leaksDetected,
      snapshot1: snapshot1.name,
      snapshot2: snapshot2.name
    };
  }

  // 自动内存监控
  startAutoMonitoring(interval = 30000) {
    if (!this.leakDetectionEnabled) return;

    this.monitoringInterval = setInterval(() => {
      const snapshotName = `auto_${Date.now()}`;
      this.takeSnapshot(snapshotName);
      
      // 保留最近10个快照
      const autoSnapshots = Array.from(this.snapshots.entries())
        .filter(([name]) => name.startsWith('auto_'))
        .sort(([,a], [,b]) => new Date(a.timestamp) - new Date(b.timestamp));
      
      if (autoSnapshots.length > 10) {
        const [oldestName] = autoSnapshots[0];
        this.snapshots.delete(oldestName);
      }
    }, interval);
  }

  // 停止自动监控
  stopAutoMonitoring() {
    if (this.monitoringInterval) {
      clearInterval(this.monitoringInterval);
      this.monitoringInterval = null;
    }
  }

  // 获取内存报告
  getMemoryReport() {
    const snapshots = Array.from(this.snapshots.values());
    return {
      currentMemory: this.getHeapInfo(),
      snapshots: snapshots,
      snapshotCount: snapshots.length
    };
  }
}

export default MemoryDebug;

网络调试

网络请求监控

监控和分析应用中的网络请求行为。

javascript
// debug/network-debug.js
class NetworkDebug {
  constructor() {
    this.requests = new Map();
    this.enabled = process.env.NODE_ENV === 'development';
  }

  // 监控 fetch 请求
  monitorFetch() {
    if (!this.enabled) return;

    const originalFetch = window.fetch;
    window.fetch = async (...args) => {
      const requestId = this.generateRequestId();
      const startTime = performance.now();
      
      this.requests.set(requestId, {
        id: requestId,
        url: args[0],
        method: 'GET', // 默认为 GET
        startTime,
        status: 'pending'
      });

      try {
        const response = await originalFetch(...args);
        const endTime = performance.now();
        const duration = endTime - startTime;

        const request = this.requests.get(requestId);
        request.endTime = endTime;
        request.duration = duration;
        request.status = response.ok ? 'success' : 'error';
        request.statusCode = response.status;
        request.responseSize = this.getResponseSize(response);

        console.log(`🌐 网络请求 ${requestId}:`, {
          url: request.url,
          状态: request.status,
          状态码: request.statusCode,
          时长: `${duration.toFixed(2)}ms`,
          大小: request.responseSize
        });

        return response;
      } catch (error) {
        const endTime = performance.now();
        const duration = endTime - startTime;

        const request = this.requests.get(requestId);
        request.endTime = endTime;
        request.duration = duration;
        request.status = 'error';
        request.error = error.message;

        console.error(`🌐 网络请求错误 ${requestId}:`, {
          url: request.url,
          错误: error.message,
          时长: `${duration.toFixed(2)}ms`
        });

        throw error;
      }
    };
  }

  // 生成请求ID
  generateRequestId() {
    return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  // 获取响应大小
  getResponseSize(response) {
    const contentLength = response.headers.get('content-length');
    if (contentLength) {
      return `${(parseInt(contentLength) / 1024).toFixed(2)} KB`;
    }
    return '未知';
  }

  // 获取网络统计
  getNetworkStats() {
    const requests = Array.from(this.requests.values());
    const successful = requests.filter(req => req.status === 'success');
    const failed = requests.filter(req => req.status === 'error');
    
    const totalDuration = successful.reduce((sum, req) => sum + req.duration, 0);
    const averageDuration = successful.length > 0 ? totalDuration / successful.length : 0;

    return {
      totalRequests: requests.length,
      successfulRequests: successful.length,
      failedRequests: failed.length,
      successRate: requests.length > 0 ? (successful.length / requests.length * 100).toFixed(2) : 0,
      averageDuration: `${averageDuration.toFixed(2)}ms`,
      lastRequest: requests[requests.length - 1]
    };
  }

  // 清空请求记录
  clearRequests() {
    this.requests.clear();
  }
}

export default NetworkDebug;

调试工具集成

综合调试管理器

集成所有调试工具的统一管理界面。

javascript
// debug/debug-manager.js
import MainProcessDebug from './main-process-debug.js';
import PerformanceDebug from './performance-debug.js';
import MemoryDebug from './memory-debug.js';
import NetworkDebug from './network-debug.js';

class DebugManager {
  constructor() {
    this.isDevelopment = process.env.NODE_ENV === 'development';
    this.tools = new Map();
    
    this.initializeTools();
  }

  initializeTools() {
    if (!this.isDevelopment) return;

    // 初始化各个调试工具
    this.tools.set('main', new MainProcessDebug());
    this.tools.set('performance', new PerformanceDebug());
    this.tools.set('memory', new MemoryDebug());
    this.tools.set('network', new NetworkDebug());

    console.log('🔧 调试管理器已初始化');
  }

  // 获取调试报告
  getDebugReport() {
    const report = {
      timestamp: new Date().toISOString(),
      environment: {
        nodeEnv: process.env.NODE_ENV,
        platform: process.platform,
        electronVersion: process.versions.electron
      },
      tools: {}
    };

    // 收集各个工具的报告
    for (const [name, tool] of this.tools) {
      if (typeof tool.getPerformanceReport === 'function') {
        report.tools[name] = tool.getPerformanceReport();
      } else if (typeof tool.getMemoryReport === 'function') {
        report.tools[name] = tool.getMemoryReport();
      } else if (typeof tool.getNetworkStats === 'function') {
        report.tools[name] = tool.getNetworkStats();
      }
    }

    return report;
  }

  // 导出调试数据
  exportDebugData() {
    const report = this.getDebugReport();
    
    // 在实际应用中,这里可以保存到文件或发送到服务器
    console.log('📋 调试报告:', report);
    
    return report;
  }

  // 启用/禁用特定调试工具
  setToolEnabled(toolName, enabled) {
    const tool = this.tools.get(toolName);
    if (tool && typeof tool.enabled !== 'undefined') {
      tool.enabled = enabled;
      console.log(`🔧 ${toolName} ${enabled ? '启用' : '禁用'}`);
    }
  }

  // 重置所有调试数据
  resetAll() {
    for (const [name, tool] of this.tools) {
      if (typeof tool.reset === 'function') {
        tool.reset();
      }
    }
    console.log('🔄 所有调试数据已重置');
  }
}

export default DebugManager;

调试界面集成

在应用中集成调试控制界面。

javascript
// debug/debug-ui.js
class DebugUI {
  constructor(debugManager) {
    this.debugManager = debugManager;
    this.uiElement = null;
    this.isVisible = false;
  }

  // 创建调试UI
  createDebugUI() {
    if (!this.debugManager.isDevelopment) return;

    const debugPanel = document.createElement('div');
    debugPanel.id = 'electron-debug-panel';
    debugPanel.style.cssText = `
      position: fixed;
      top: 10px;
      right: 10px;
      background: rgba(0,0,0,0.8);
      color: white;
      padding: 10px;
      border-radius: 5px;
      font-family: monospace;
      font-size: 12px;
      z-index: 10000;
      max-width: 300px;
      max-height: 400px;
      overflow: auto;
    `;

    this.uiElement = debugPanel;
    this.updateUI();
    document.body.appendChild(debugPanel);

    // 添加键盘快捷键
    this.setupKeyboardShortcuts();
  }

  // 更新UI内容
  updateUI() {
    if (!this.uiElement) return;

    const report = this.debugManager.getDebugReport();
    
    this.uiElement.innerHTML = `
      <div style="margin-bottom: 10px;">
        <strong>Electron 调试面板</strong>
        <button onclick="debugUI.toggleVisibility()" style="float: right;">隐藏</button>
      </div>
      <div style="font-size: 10px;">
        <div>平台: ${report.environment.platform}</div>
        <div>Electron: ${report.environment.electronVersion}</div>
        <div>环境: ${report.environment.nodeEnv}</div>
        <hr style="margin: 5px 0;">
        <div>性能测量: ${report.tools.performance?.summary?.totalEntries || 0} 次</div>
        <div>内存快照: ${report.tools.memory?.snapshotCount || 0} 个</div>
        <div>网络请求: ${report.tools.network?.totalRequests || 0} 次</div>
        <hr style="margin: 5px 0;">
        <button onclick="debugManager.exportDebugData()">导出报告</button>
        <button onclick="debugManager.resetAll()">重置数据</button>
      </div>
    `;
  }

  // 切换UI可见性
  toggleVisibility() {
    this.isVisible = !this.isVisible;
    this.uiElement.style.display = this.isVisible ? 'block' : 'none';
  }

  // 设置键盘快捷键
  setupKeyboardShortcuts() {
    document.addEventListener('keydown', (event) => {
      // Ctrl+Shift+D 切换调试面板
      if (event.ctrlKey && event.shiftKey && event.key === 'D') {
        event.preventDefault();
        this.toggleVisibility();
      }
    });
  }

  // 定期更新UI
  startAutoUpdate(interval = 2000) {
    setInterval(() => {
      if (this.isVisible) {
        this.updateUI();
      }
    }, interval);
  }
}

// 全局调试实例
window.debugManager = new DebugManager();
window.debugUI = new DebugUI(window.debugManager);

// 初始化调试UI
document.addEventListener('DOMContentLoaded', () => {
  window.debugUI.createDebugUI();
  window.debugUI.startAutoUpdate();
});

生产环境调试

远程调试配置

配置生产环境的远程调试能力,支持现场问题诊断。

javascript
// debug/remote-debug.js
import { app, BrowserWindow, ipcMain } from 'electron';

class RemoteDebug {
  constructor() {
    this.remoteDebuggingEnabled = false;
    this.debugPort = 8315;
  }

  // 启用远程调试
  enableRemoteDebugging() {
    if (this.remoteDebuggingEnabled) return;

    // 设置远程调试端口
    app.commandLine.appendSwitch('remote-debugging-port', this.debugPort.toString());
    
    this.setupRemoteDebugHandlers();
    this.remoteDebuggingEnabled = true;

    console.log(`🔧 远程调试已启用,端口: ${this.debugPort}`);
  }

  setupRemoteDebugHandlers() {
    // 处理远程调试命令
    ipcMain.handle('remote-debug-command', (event, command, data) => {
      switch (command) {
        case 'get-debug-info':
          return this.getDebugInfo();
        case 'take-heap-snapshot':
          return this.takeHeapSnapshot();
        case 'get-performance-metrics':
          return this.getPerformanceMetrics();
        default:
          throw new Error(`未知的调试命令: ${command}`);
      }
    });
  }

  getDebugInfo() {
    return {
      platform: process.platform,
      arch: process.arch,
      electronVersion: process.versions.electron,
      chromeVersion: process.versions.chrome,
      nodeVersion: process.versions.node,
      memoryUsage: process.memoryUsage(),
      uptime: process.uptime(),
      remoteDebuggingPort: this.debugPort
    };
  }

  takeHeapSnapshot() {
    // 在实际应用中,这里可以实现堆快照功能
    console.log('📸 堆快照请求已接收');
    return { success: true, message: '堆快照功能需要额外实现' };
  }

  getPerformanceMetrics() {
    const performanceMetrics = {
      timestamp: new Date().toISOString(),
      memory: process.memoryUsage(),
      cpu: process.cpuUsage(),
      uptime: process.uptime()
    };

    return performanceMetrics;
  }

  // 生成调试访问URL
  getDebugURL() {
    return `http://localhost:${this.debugPort}`;
  }
}

export default RemoteDebug;

通过系统化的调试工具和技术的集成,Electron 应用可以实现从开发到生产全生命周期的有效调试和问题诊断。

Electron 调试已经加载完毕