mcpField
E
electrobun-debugging

electrobun-debugging

github.com/rajavijayach开发1161 次安装36 周前更新
代码仓库

关于 electrobun-debugging

electrobun-debugging 是 Electrobun 应用的故障排查指南,面向开发者,涵盖主进程、Webview、RPC 与性能问题的调试方法。

主要功能

  1. 01主进程日志与调试器
  2. 02Webview DevTools 调试
  3. 03RPC 通信排查
  4. 04CPU 与内存分析
  5. 05常见构建及运行问题处理

适用场景

  1. 01定位主进程异常
  2. 02检查 Webview 错误与日志
  3. 03排查 RPC 调用故障
  4. 04分析性能或内存问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rajavijayach/electrobun-skills --skill electrobun-debugging

安装后在 Claude Code 中输入/electrobun-debugging确认已加载。

详细介绍

Electrobun 调试

Electrobun 应用的全面调试与故障排除指南。

开发环境

基本开发设置
# Development mode with hot reload
bun run dev

# Development mode with verbose logging
DEBUG=* bun run dev

# Development mode with specific debug namespace
DEBUG=electrobun:* bun run dev
环境配置

.env.development:

# Enable development features
NODE_ENV=development
DEBUG=electrobun:*

# DevTools always open
ELECTRON_ENABLE_DEVTOOLS=1

# Disable security warnings in dev
ELECTRON_DISABLE_SECURITY_WARNINGS=true

# Custom dev server port
DEV_SERVER_PORT=3000

调试主进程

控制台日志
// Main process logs appear in terminal
console.log("Main process started");
console.error("Error in main process");
console.warn("Warning in main process");

// Structured logging
const logger = {
  debug: (msg: string, data?: any) => {
    if (process.env.DEBUG) {
      console.log(`[DEBUG] ${msg}`, data || "");
    }
  },
  info: (msg: string, data?: any) => {
    console.log(`[INFO] ${msg}`, data || "");
  },
  error: (msg: string, error?: any) => {
    console.error(`[ERROR] ${msg}`, error || "");
    if (error?.stack) {
      console.error(error.stack);
    }
  }
};

logger.info("Window created", { width: 1200, height: 800 });
logger.error("Failed to load file", error);
Bun 调试器
# Start with Bun debugger
bun --inspect run dev

# With breakpoint on first line
bun --inspect-brk run dev

# Connect with Chrome DevTools
# Open chrome://inspect in Chrome
# Click "inspect" on your process
主进程中的错误处理
// Global error handlers
process.on("uncaughtException", (error) => {
  logger.error("Uncaught exception", error);
  
  // Show error dialog
  dialog.showMessageBox({
    type: "error",
    title: "Application Error",
    message: "An unexpected error occurred",
    detail: error.message,
  });
  
  // Optional: restart or quit
  // app.relaunch();
  // app.quit();
});

process.on("unhandledRejection", (reason, promise) => {
  logger.error("Unhandled rejection", { reason, promise });
});

// Window error handler
win.on("error", (error) => {
  logger.error("Window error", error);
});

// RPC error handling
win.defineRpc({
  handlers: {
    async someHandler(args: any) {
      try {
        // Handler logic
        return { success: true };
      } catch (error) {
        logger.error("RPC handler error", error);
        throw error; // Re-throw to send to webview
      }
    }
  }
});

调试 Webview

Chrome DevTools
// Open DevTools programmatically
win.openDevTools();

// Open DevTools detached
win.openDevTools({ mode: "detach" });

// Toggle DevTools
win.toggleDevTools();

// Close DevTools
win.closeDevTools();

// Menu item to toggle DevTools
{
  label: "Toggle Developer Tools",
  accelerator: "CmdOrCtrl+Shift+I",
  action: () => win.toggleDevTools()
}
Webview 中的控制台日志
// Webview console logs appear in DevTools
console.log("Webview initialized");
console.error("Error in webview");
console.warn("Warning in webview");
console.table({ user: "Alice", age: 30 });

// Custom logger
const logger = {
  log: (msg: string, ...args: any[]) => {
    console.log(`[${new Date().toISOString()}] ${msg}`, ...args);
  },
  group: (label: string) => {
    console.group(label);
  },
  groupEnd: () => {
    console.groupEnd();
  }
};

logger.group("User Login");
logger.log("Validating credentials");
logger.log("Fetching user data");
logger.groupEnd();
捕获 Webview 错误
// Global error handler
window.addEventListener("error", (event) => {
  console.error("Uncaught error:", event.error);
  
  // Send to main process for logging
  electroview.rpc.logError({
    message: event.error.message,
    stack: event.error.stack,
    url: event.filename,
    line: event.lineno,
    column: event.colno,
  });
});

// Unhandled promise rejections
window.addEventListener("unhandledrejection", (event) => {
  console.error("Unhandled rejection:", event.reason);
  
  electroview.rpc.logError({
    message: "Unhandled rejection",
    reason: event.reason,
  });
});

// Main process handler
win.defineRpc({
  handlers: {
    async logError(error: any) {
      logger.error("Webview error", error);
      
      // Optional: save to file
      await saveErrorLog(error);
    }
  }
});

调试 RPC 通信

RPC 日志
// Main process RPC logger
class RpcLogger {
  wrap(handlers: any) {
    const wrapped: any = {};
    
    for (const [name, handler] of Object.entries(handlers)) {
      wrapped[name] = async (...args: any[]) => {
        const callId = Math.random().toString(36).slice(2);
        
        logger.debug(`[RPC:${callId}] → ${name}`, args);
        const startTime = Date.now();
        
        try {
          const result = await (handler as Function)(...args);
          const duration = Date.now() - startTime;
          logger.debug(`[RPC:${callId}] ← ${name} (${duration}ms)`, result);
          return result;
        } catch (error) {
          const duration = Date.now() - startTime;
          logger.error(`[RPC:${callId}] ✗ ${name} (${duration}ms)`, error);
          throw error;
        }
      };
    }
    
    return wrapped;
  }
}

const rpcLogger = new RpcLogger();

win.defineRpc({
  handlers: rpcLogger.wrap({
    async getUser(id: string) {
      return await database.users.findById(id);
    },
    async saveFile(path: string, content: string) {
      await Bun.write(path, content);
      return { success: true };
    }
  })
});
在 DevTools 中测试 RPC
// In webview DevTools console:

// Test RPC call
await electroview.rpc.getUser("123")

// Test error handling
try {
  await electroview.rpc.invalidMethod()
} catch (error) {
  console.error("Expected error:", error);
}

// Measure RPC performance
console.time("RPC call");
const result = await electroview.rpc.getUser("123");
console.timeEnd("RPC call");

性能分析

CPU 性能分析
// Main process CPU profiling
const { performance, PerformanceObserver } = require("perf_hooks");

const obs = new PerformanceObserver((items) => {
  items.getEntries().forEach(entry => {
    logger.debug(`${entry.name}: ${entry.duration}ms`);
  });
});

obs.observe({ entryTypes: ["measure"] });

// Measure operation
performance.mark("operation-start");
await expensiveOperation();
performance.mark("operation-end");
performance.measure("operation", "operation-start", "operation-end");

Webview CPU 性能分析:

// Use Chrome DevTools Performance tab
// Or programmatically:
console.profile("My Operation");
await performOperation();
console.profileEnd("My Operation");

// Simple timing
const start = performance.now();
await operation();
const duration = performance.now() - start;
console.log(`Operation took ${duration}ms`);
内存性能分析
// Main process memory usage
function logMemoryUsage() {
  const usage = process.memoryUsage();
  logger.info("Memory usage", {
    heapUsed: `${Math.round(usage.heapUsed / 1024 / 1024)}MB`,
    heapTotal: `${Math.round(usage.heapTotal / 1024 / 1024)}MB`,
    external: `${Math.round(usage.external / 1024 / 1024)}MB`,
    rss: `${Math.round(usage.rss / 1024 / 1024)}MB`,
  });
}

// Monitor memory over time
setInterval(logMemoryUsage, 10000);

// Force garbage collection (development only)
if (global.gc) {
  global.gc();
  logMemoryUsage();
}

Webview 内存性能分析:

// Use Chrome DevTools Memory tab
// Or programmatically:
if (performance.memory) {
  console.log("Memory:", {
    used: `${Math.round(performance.memory.usedJSHeapSize / 1024 / 1024)}MB`,
    total: `${Math.round(performance.memory.totalJSHeapSize / 1024 / 1024)}MB`,
    limit: `${Math.round(performance.memory.jsHeapSizeLimit / 1024 / 1024)}MB`,
  });
}

常见问题与解决方案

构建错误

问题:“Cannot find module 'electrobun'”

# Solution: Install dependencies
bun install

# Verify electrobun is installed
bun pm ls electrobun

问题:原生模块编译失败

# macOS: Install Xcode Command Line Tools
xcode-select --install

# Windows: Install Visual Studio Build Tools
# Download from visualstudio.microsoft.com

# Linux: Install build essentials
sudo apt install build-essential

问题:“WebView2 not found”(Windows)

# Install WebView2 Runtime
# Download from microsoft.com/edge/webview2
运行时错误

问题:窗口未显示

// Debug checklist:
// 1. Check window is created
console.log("Window created:", win);

// 2. Explicitly show window
win.show();

// 3. Check window bounds
console.log("Window bounds:", win.getBounds());

// 4. Check if window is minimized/hidden
console.log("Window visible:", win.isVisible());
console.log("Window minimized:", win.isMinimized());

问题:RPC 无法正常工作

// Debug checklist:
// 1. Verify RPC handlers defined
console.log("RPC handlers:", Object.keys(handlers));

// 2. Check webview loaded
win.on("did-finish-load", () => {
  console.log("Webview loaded");
});

// 3. Test RPC with try-catch
try {
  const result = await electroview.rpc.testMethod();
  console.log("RPC working:", result);
} catch (error) {
  console.error("RPC error:", error);
}

// 4. Check for CORS issues in webview
// 5. Verify Electroview initialized in webview

问题:内存使用量过高

// Common causes:
// 1. Memory leaks from event listeners
window.removeEventListener("resize", handler);

// 2. Large data stored in closures
// Use WeakMap/WeakSet for object references

// 3. Not cleaning up resources
win.on("close", () => {
  // Clean up timers
  clearInterval(intervalId);
  // Close connections
  ws.close();
  // Release resources
  cache.clear();
});
特定平台的问题

macOS:

// Issue: App won't open (Gatekeeper)
// Solution: Code sign and notarize

// Issue: Permissions denied
// Solution: Add Info.plist entries
<key>NSCameraUsageDescription</key>
<string>App needs camera access</string>
<key>NSMicrophoneUsageDescription</key>
<string>App needs microphone access</string>

Windows:

// Issue: SmartScreen warning
// Solution: Code sign with trusted certificate

// Issue: Antivirus blocking
// Solution: Code sign and submit to vendors

Linux:

// Issue: WebKit crashes
// Solution: Install webkit2gtk-4.1
sudo apt install libwebkit2gtk-4.1-dev

// Issue: Missing libraries
// Solution: Check dependencies
ldd dist/MyApp

调试工具

网络检查
// Intercept network requests
win.on("will-navigate", (event) => {
  logger.debug("Navigating to:", event.url);
  
  // Block navigation if needed
  if (event.url.includes("blocked.com")) {
    event.preventDefault();
  }
});

// Monitor requests in DevTools Network tab
// Or programmatically:
win.webContents.session.webRequest.onBeforeRequest((details, callback) => {
  logger.debug("Request:", details.url);
  callback({});
});
源映射

确保启用源映射,以便更好地调试:

// tsconfig.json
{
  "compilerOptions": {
    "sourceMap": true,
    "inlineSourceMap": false,
    "inlineSources": true
  }
}

系统化调试方法

// 1. Reproduce the issue consistently
// 2. Isolate the problem (main vs webview)
// 3. Add logging around suspected code
// 4. Use breakpoints in DevTools/debugger
// 5. Check error messages and stack traces
// 6. Review recent changes (git diff)
// 7. Test in isolation (minimal reproduction)
// 8. Check documentation and examples
// 9. Search issues on GitHub
// 10. Ask on Discord

// Debugging template
async function debugIssue() {
  logger.info("=== Debug Session Started ===");
  logger.info("Environment:", {
    platform: process.platform,
    version: app.getVersion(),
    development: process.env.NODE_ENV === "development",
  });
  
  try {
    logger.info("Step 1: Initialize");
    // ...
    
    logger.info("Step 2: Execute");
    // ...
    
    logger.info("Step 3: Verify");
    // ...
    
    logger.info("=== Debug Session Complete ===");
  } catch (error) {
    logger.error("=== Debug Session Failed ===", error);
    throw error;
  }
}

资源

了解更多 Electrobun 相关信息:

评论

支持 Markdown