electrobun-debugging
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseElectrobun Debugging
Electrobun调试
Comprehensive debugging and troubleshooting guide for Electrobun applications.
Electrobun应用的全面调试与故障排除指南。
Development Environment
开发环境
Basic Development Setup
基础开发环境搭建
bash
undefinedbash
undefinedDevelopment mode with hot reload
启用热重载的开发模式
bun run dev
bun run dev
Development mode with verbose logging
启用详细日志的开发模式
DEBUG=* bun run dev
DEBUG=* bun run dev
Development mode with specific debug namespace
启用特定调试命名空间的开发模式
DEBUG=electrobun:* bun run dev
undefinedDEBUG=electrobun:* bun run dev
undefinedEnvironment Configuration
环境配置
.env.development:
bash
undefined.env.development:
bash
undefinedEnable development features
启用开发功能
NODE_ENV=development
DEBUG=electrobun:*
NODE_ENV=development
DEBUG=electrobun:*
DevTools always open
始终打开DevTools
ELECTRON_ENABLE_DEVTOOLS=1
ELECTRON_ENABLE_DEVTOOLS=1
Disable security warnings in dev
禁用开发环境中的安全警告
ELECTRON_DISABLE_SECURITY_WARNINGS=true
ELECTRON_DISABLE_SECURITY_WARNINGS=true
Custom dev server port
自定义开发服务器端口
DEV_SERVER_PORT=3000
undefinedDEV_SERVER_PORT=3000
undefinedDebugging Main Process
主进程调试
Console Logging
控制台日志
ts
// 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);ts
// 主进程日志会显示在终端中
console.log("Main process started");
console.error("Error in main process");
console.warn("Warning in main process");
// 结构化日志
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 Debugger
Bun调试器
bash
undefinedbash
undefinedStart with Bun debugger
启动Bun调试器
bun --inspect run dev
bun --inspect run dev
With breakpoint on first line
在第一行设置断点启动
bun --inspect-brk run dev
bun --inspect-brk run dev
Connect with Chrome DevTools
连接Chrome DevTools
Open chrome://inspect in Chrome
在Chrome中打开chrome://inspect
Click "inspect" on your process
点击进程对应的"inspect"
undefinedundefinedError Handling in Main
主进程错误处理
ts
// 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
}
}
}
});ts
// 全局错误处理器
process.on("uncaughtException", (error) => {
logger.error("Uncaught exception", error);
// 显示错误对话框
dialog.showMessageBox({
type: "error",
title: "Application Error",
message: "An unexpected error occurred",
detail: error.message,
});
// 可选:重启或退出应用
// app.relaunch();
// app.quit();
});
process.on("unhandledRejection", (reason, promise) => {
logger.error("Unhandled rejection", { reason, promise });
});
// 窗口错误处理器
win.on("error", (error) => {
logger.error("Window error", error);
});
// RPC错误处理
win.defineRpc({
handlers: {
async someHandler(args: any) {
try {
// 处理器逻辑
return { success: true };
} catch (error) {
logger.error("RPC handler error", error);
throw error; // 重新抛出错误至webview
}
}
}
});Debugging Webview
Webview调试
Chrome DevTools
Chrome DevTools
ts
// 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()
}ts
// 以编程方式打开DevTools
win.openDevTools();
// 以分离模式打开DevTools
win.openDevTools({ mode: "detach" });
// 切换DevTools显示状态
win.toggleDevTools();
// 关闭DevTools
win.closeDevTools();
// 用于切换DevTools的菜单项
{
label: "Toggle Developer Tools",
accelerator: "CmdOrCtrl+Shift+I",
action: () => win.toggleDevTools()
}Console Logging in Webview
Webview控制台日志
ts
// 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();ts
// Webview控制台日志会显示在DevTools中
console.log("Webview initialized");
console.error("Error in webview");
console.warn("Warning in webview");
console.table({ user: "Alice", age: 30 });
// 自定义日志器
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();Capturing Webview Errors
捕获Webview错误
ts
// 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);
}
}
});ts
// 全局错误处理器
window.addEventListener("error", (event) => {
console.error("Uncaught error:", event.error);
// 将错误发送至主进程记录
electroview.rpc.logError({
message: event.error.message,
stack: event.error.stack,
url: event.filename,
line: event.lineno,
column: event.colno,
});
});
// 未处理的Promise拒绝
window.addEventListener("unhandledrejection", (event) => {
console.error("Unhandled rejection:", event.reason);
electroview.rpc.logError({
message: "Unhandled rejection",
reason: event.reason,
});
});
// 主进程处理器
win.defineRpc({
handlers: {
async logError(error: any) {
logger.error("Webview error", error);
// 可选:将错误保存至文件
await saveErrorLog(error);
}
}
});Debugging RPC Communication
RPC通信调试
RPC Logging
RPC日志
ts
// 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 };
}
})
});ts
// 主进程RPC日志器
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 };
}
})
});Testing RPC in DevTools
在DevTools中测试RPC
ts
// 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");ts
// 在webview的DevTools控制台中:
// 测试RPC调用
await electroview.rpc.getUser("123")
// 测试错误处理
try {
await electroview.rpc.invalidMethod()
} catch (error) {
console.error("Expected error:", error);
}
// 测量RPC性能
console.time("RPC call");
const result = await electroview.rpc.getUser("123");
console.timeEnd("RPC call");Performance Profiling
性能分析
CPU Profiling
CPU分析
ts
// 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 profiling:
ts
// 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`);ts
// 主进程CPU分析
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"] });
// 测量操作耗时
performance.mark("operation-start");
await expensiveOperation();
performance.mark("operation-end");
performance.measure("operation", "operation-start", "operation-end");Webview CPU分析:
ts
// 使用Chrome DevTools的Performance面板
// 或通过编程方式:
console.profile("My Operation");
await performOperation();
console.profileEnd("My Operation");
// 简单计时
const start = performance.now();
await operation();
const duration = performance.now() - start;
console.log(`Operation took ${duration}ms`);Memory Profiling
内存分析
ts
// 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 memory profiling:
ts
// 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`,
});
}ts
// 主进程内存使用情况
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`,
});
}
// 定期监控内存使用情况
setInterval(logMemoryUsage, 10000);
// 强制垃圾回收(仅开发环境可用)
if (global.gc) {
global.gc();
logMemoryUsage();
}Webview内存分析:
ts
// 使用Chrome DevTools的Memory面板
// 或通过编程方式:
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`,
});
}Common Issues & Solutions
常见问题与解决方案
Build Errors
构建错误
Issue: "Cannot find module 'electrobun'"
bash
undefined问题:"Cannot find module 'electrobun'"
bash
undefinedSolution: Install dependencies
解决方案:安装依赖
bun install
bun install
Verify electrobun is installed
验证electrobun是否已安装
bun pm ls electrobun
**Issue: Native module compilation fails**
```bashbun pm ls electrobun
**问题:原生模块编译失败**
```bashmacOS: Install Xcode Command Line Tools
macOS:安装Xcode命令行工具
xcode-select --install
xcode-select --install
Windows: Install Visual Studio Build Tools
Windows:安装Visual Studio构建工具
Download from visualstudio.microsoft.com
从visualstudio.microsoft.com下载
Linux: Install build essentials
Linux:安装构建必备组件
sudo apt install build-essential
**Issue: "WebView2 not found" (Windows)**
```bashsudo apt install build-essential
**问题:"WebView2 not found"(Windows)**
```bashInstall WebView2 Runtime
安装WebView2运行时
Download from microsoft.com/edge/webview2
从microsoft.com/edge/webview2下载
undefinedundefinedRuntime Errors
运行时错误
Issue: Window not showing
ts
// 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());Issue: RPC not working
ts
// 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 webviewIssue: High memory usage
ts
// 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();
});问题:窗口未显示
ts
// 调试检查清单:
// 1. 检查窗口是否已创建
console.log("Window created:", win);
// 2. 显式显示窗口
win.show();
// 3. 检查窗口边界
console.log("Window bounds:", win.getBounds());
// 4. 检查窗口是否最小化/隐藏
console.log("Window visible:", win.isVisible());
console.log("Window minimized:", win.isMinimized());问题:RPC无法工作
ts
// 调试检查清单:
// 1. 验证RPC处理器是否已定义
console.log("RPC handlers:", Object.keys(handlers));
// 2. 检查webview是否已加载完成
win.on("did-finish-load", () => {
console.log("Webview loaded");
});
// 3. 使用try-catch测试RPC
try {
const result = await electroview.rpc.testMethod();
console.log("RPC working:", result);
} catch (error) {
console.error("RPC error:", error);
}
// 4. 检查webview中的CORS问题
// 5. 验证Electroview是否已在webview中初始化问题:内存占用过高
ts
// 常见原因:
// 1. 事件监听器导致的内存泄漏
window.removeEventListener("resize", handler);
// 2. 闭包中存储了大量数据
// 使用WeakMap/WeakSet存储对象引用
// 3. 未清理资源
win.on("close", () => {
// 清理定时器
clearInterval(intervalId);
// 关闭连接
ws.close();
// 释放缓存
cache.clear();
});Platform-Specific Issues
平台特定问题
macOS:
ts
// 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:
ts
// Issue: SmartScreen warning
// Solution: Code sign with trusted certificate
// Issue: Antivirus blocking
// Solution: Code sign and submit to vendorsLinux:
ts
// Issue: WebKit crashes
// Solution: Install webkit2gtk-4.1
sudo apt install libwebkit2gtk-4.1-dev
// Issue: Missing libraries
// Solution: Check dependencies
ldd dist/MyAppmacOS:
ts
// 问题:应用无法打开(Gatekeeper限制)
// 解决方案:进行代码签名与公证
// 问题:权限被拒绝
// 解决方案:在Info.plist中添加权限条目
<key>NSCameraUsageDescription</key>
<string>App needs camera access</string>
<key>NSMicrophoneUsageDescription</key>
<string>App needs microphone access</string>Windows:
ts
// 问题:SmartScreen警告
// 解决方案:使用可信证书进行代码签名
// 问题:被杀毒软件拦截
// 解决方案:进行代码签名并提交至厂商Linux:
ts
// 问题:WebKit崩溃
// 解决方案:安装webkit2gtk-4.1
sudo apt install libwebkit2gtk-4.1-dev
// 问题:缺少依赖库
// 解决方案:检查依赖项
ldd dist/MyAppDebugging Tools
调试工具
Network Inspection
网络检查
ts
// 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({});
});ts
// 拦截网络请求
win.on("will-navigate", (event) => {
logger.debug("Navigating to:", event.url);
// 如有需要可阻止导航
if (event.url.includes("blocked.com")) {
event.preventDefault();
}
});
// 在DevTools的Network面板中监控请求
// 或通过编程方式:
win.webContents.session.webRequest.onBeforeRequest((details, callback) => {
logger.debug("Request:", details.url);
callback({});
});Source Maps
源映射
Ensure source maps are enabled for better debugging:
ts
// tsconfig.json
{
"compilerOptions": {
"sourceMap": true,
"inlineSourceMap": false,
"inlineSources": true
}
}确保启用源映射以提升调试体验:
ts
// tsconfig.json
{
"compilerOptions": {
"sourceMap": true,
"inlineSourceMap": false,
"inlineSources": true
}
}Systematic Debugging Approach
系统化调试方法
ts
// 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;
}
}ts
// 1. 稳定复现问题
// 2. 隔离问题(主进程vs webview)
// 3. 在可疑代码周围添加日志
// 4. 在DevTools/调试器中使用断点
// 5. 查看错误信息与堆栈跟踪
// 6. 检查最近的代码变更(git diff)
// 7. 隔离测试(最小化复现案例)
// 8. 查阅文档与示例
// 9. 在GitHub上搜索相关问题
// 10. 在Discord上求助
// 调试模板
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;
}
}Resources
资源
For more on Electrobun:
- Core skill: - Basic setup
electrobun - RPC patterns: - RPC debugging
electrobun-rpc-patterns - Distribution: - Build issues
electrobun-distribution - GitHub Issues: https://github.com/blackboardsh/electrobun/issues
- Discord: https://discord.gg/ueKE4tjaCE
更多关于Electrobun的资源:
- 核心技能: - 基础搭建
electrobun - RPC模式: - RPC调试
electrobun-rpc-patterns - 分发部署: - 构建问题
electrobun-distribution - GitHub Issues: https://github.com/blackboardsh/electrobun/issues
- Discord: https://discord.gg/ueKE4tjaCE