electrobun-best-practices

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Electrobun Best Practices

Electrobun最佳实践

Electrobun builds cross-platform desktop apps with TypeScript and Bun. This skill gives safe defaults, typed RPC patterns, and operational guidance for build/update/distribution.
Electrobun 基于 TypeScript 和 Bun 构建跨平台桌面应用。本技能提供了构建/更新/分发环节的安全默认配置、类型化RPC模式以及操作指导。

Pair with TypeScript Best Practices

搭配TypeScript最佳实践使用

Always load
typescript-best-practices
alongside this skill.
请始终同时加载
typescript-best-practices
技能。

Version and Freshness

版本与时效性

Electrobun APIs evolve quickly. Before relying on advanced options or platform-specific behavior, verify against current docs and CLI output.
Electrobun API迭代速度较快。在使用高级选项或平台特定功能前,请务必对照最新文档和CLI输出进行验证。

Architecture

架构

Electrobun apps run as Bun apps:
  • Bun process (main): imports from
    electrobun/bun
  • Browser context (views): imports from
    electrobun/view
  • Shared types: RPC schemas shared between both contexts
IPC between bun and browser contexts uses postMessage, FFI, and (in some paths) encrypted WebSockets.
Electrobun应用以Bun应用的形式运行:
  • Bun进程(主进程):从
    electrobun/bun
    导入模块
  • 浏览器上下文(视图层):从
    electrobun/view
    导入模块
  • 共享类型:主进程与视图层之间共享的RPC模式定义
Bun进程与浏览器上下文之间的IPC通信使用postMessage、FFI,部分场景下会使用加密WebSocket。

Quick Start

快速开始

bash
bunx electrobun init
bun install
bun start
Recommended scripts:
json
{
  "scripts": {
    "start": "electrobun run",
    "dev": "electrobun dev",
    "dev:watch": "electrobun dev --watch",
    "build:dev": "bun install && electrobun build",
    "build:canary": "electrobun build --env=canary",
    "build:stable": "electrobun build --env=stable"
  }
}
bash
bunx electrobun init
bun install
bun start
推荐脚本配置:
json
{
  "scripts": {
    "start": "electrobun run",
    "dev": "electrobun dev",
    "dev:watch": "electrobun dev --watch",
    "build:dev": "bun install && electrobun build",
    "build:canary": "electrobun build --env=canary",
    "build:stable": "electrobun build --env=stable"
  }
}

Secure Defaults

安全默认配置

Use this baseline for untrusted or third-party content:
typescript
import { BrowserWindow } from "electrobun/bun";

const win = new BrowserWindow({
  title: "External Content",
  url: "https://example.com",
  sandbox: true,                  // disables RPC, events still work
  partition: "persist:external",
});

win.webview.setNavigationRules([
  "^*",                          // block everything by default
  "*://example.com/*",           // allow only trusted domain(s)
  "^http://*",                   // enforce HTTPS
]);

win.webview.on("will-navigate", (e) => {
  console.log("nav", e.data.url, "allowed", e.data.allowed);
});
Security checklist:
  • Use
    sandbox: true
    for untrusted content.
  • Apply strict navigation allowlists.
  • Use separate
    partition
    values for isolation.
  • Validate all
    host-message
    payloads from
    <electrobun-webview>
    preload scripts.
  • Do not write to
    PATHS.RESOURCES_FOLDER
    at runtime; use
    Utils.paths.userData
    .
以下是处理不可信或第三方内容的基准配置:
typescript
import { BrowserWindow } from "electrobun/bun";

const win = new BrowserWindow({
  title: "External Content",
  url: "https://example.com",
  sandbox: true,                  // 禁用RPC,事件仍可正常工作
  partition: "persist:external",
});

win.webview.setNavigationRules([
  "^*",                          // 默认阻止所有请求
  "*://example.com/*",           // 仅允许可信域名
  "^http://*",                   // 强制使用HTTPS
]);

win.webview.on("will-navigate", (e) => {
  console.log("nav", e.data.url, "allowed", e.data.allowed);
});
安全检查清单:
  • 处理不可信内容时启用
    sandbox: true
  • 应用严格的导航白名单规则。
  • 使用独立的
    partition
    值实现隔离。
  • 验证来自
    <electrobun-webview>
    预加载脚本的所有
    host-message
    负载。
  • 运行时请勿写入
    PATHS.RESOURCES_FOLDER
    ;请使用
    Utils.paths.userData

Typed RPC (Minimal Pattern)

类型化RPC(最简模式)

typescript
// src/shared/types.ts
import type { RPCSchema } from "electrobun/bun";

export type MyRPC = {
  bun: RPCSchema<{
    requests: {
      getUser: { params: { id: string }; response: { name: string } };
    };
    messages: {
      logToBun: { msg: string };
    };
  }>;
  webview: RPCSchema<{
    requests: {
      updateUI: { params: { html: string }; response: boolean };
    };
    messages: {
      notify: { text: string };
    };
  }>;
};
typescript
// bun side
import { BrowserView, BrowserWindow } from "electrobun/bun";
import type { MyRPC } from "../shared/types";

const rpc = BrowserView.defineRPC<MyRPC>({
  handlers: {
    requests: {
      getUser: ({ id }) => ({ name: `user-${id}` }),
    },
    messages: {
      logToBun: ({ msg }) => console.log(msg),
    },
  },
});

const win = new BrowserWindow({
  title: "App",
  url: "views://mainview/index.html",
  rpc,
});

await win.webview.rpc.updateUI({ html: "<p>Hello</p>" });
typescript
// browser side
import { Electroview } from "electrobun/view";
import type { MyRPC } from "../shared/types";

const rpc = Electroview.defineRPC<MyRPC>({
  handlers: {
    requests: {
      updateUI: ({ html }) => {
        document.body.innerHTML = html;
        return true;
      },
    },
    messages: {
      notify: ({ text }) => console.log(text),
    },
  },
});

const electroview = new Electroview({ rpc });
await electroview.rpc.request.getUser({ id: "1" });
electroview.rpc.send.logToBun({ msg: "hello" });
typescript
// src/shared/types.ts
import type { RPCSchema } from "electrobun/bun";

export type MyRPC = {
  bun: RPCSchema<{
    requests: {
      getUser: { params: { id: string }; response: { name: string } };
    };
    messages: {
      logToBun: { msg: string };
    };
  }>;
  webview: RPCSchema<{
    requests: {
      updateUI: { params: { html: string }; response: boolean };
    };
    messages: {
      notify: { text: string };
    };
  }>;
};
typescript
// bun side
import { BrowserView, BrowserWindow } from "electrobun/bun";
import type { MyRPC } from "../shared/types";

const rpc = BrowserView.defineRPC<MyRPC>({
  handlers: {
    requests: {
      getUser: ({ id }) => ({ name: `user-${id}` }),
    },
    messages: {
      logToBun: ({ msg }) => console.log(msg),
    },
  },
});

const win = new BrowserWindow({
  title: "App",
  url: "views://mainview/index.html",
  rpc,
});

await win.webview.rpc.updateUI({ html: "<p>Hello</p>" });
typescript
// browser side
import { Electroview } from "electrobun/view";
import type { MyRPC } from "../shared/types";

const rpc = Electroview.defineRPC<MyRPC>({
  handlers: {
    requests: {
      updateUI: ({ html }) => {
        document.body.innerHTML = html;
        return true;
      },
    },
    messages: {
      notify: ({ text }) => console.log(text),
    },
  },
});

const electroview = new Electroview({ rpc });
await electroview.rpc.request.getUser({ id: "1" });
electroview.rpc.send.logToBun({ msg: "hello" });

Events and Shutdown

事件与关机处理

Use
before-quit
for shutdown cleanup instead of relying on
process.on("exit")
for async work.
typescript
import Electrobun from "electrobun/bun";

Electrobun.events.on("before-quit", async (e) => {
  await saveState();
  // e.response = { allow: false }; // optional: cancel quit
});
Important caveat:
  • Linux currently has a caveat where some system-initiated quit paths (for example Ctrl+C/window-manager/taskbar quit) may not fire
    before-quit
    . Programmatic quit via
    Utils.quit()
    /
    process.exit()
    is reliable.
请使用
before-quit
事件进行关机清理操作,而非依赖
process.on("exit")
处理异步任务。
typescript
import Electrobun from "electrobun/bun";

Electrobun.events.on("before-quit", async (e) => {
  await saveState();
  // e.response = { allow: false }; // 可选:取消关机操作
});
重要注意事项:
  • 目前Linux平台存在一个限制:部分由系统触发的关机流程(例如Ctrl+C/窗口管理器/任务栏关闭)可能不会触发
    before-quit
    事件。通过
    Utils.quit()
    /
    process.exit()
    执行的程序化关机则是可靠的。

Common Patterns

常见模式

  • Keyboard shortcuts (copy/paste/undo): define an Edit
    ApplicationMenu
    with role-based items.
  • Tray-only app: set
    runtime.exitOnLastWindowClosed: false
    , then drive UX from
    Tray
    .
  • Multi-account isolation: use separate
    partition
    values per account.
  • Chromium consistency: set
    bundleCEF: true
    and
    defaultRenderer: "cef"
    in platform config.
  • 键盘快捷键(复制/粘贴/撤销):定义一个包含基于角色项的编辑
    ApplicationMenu
  • 仅托盘应用:设置
    runtime.exitOnLastWindowClosed: false
    ,然后通过
    Tray
    驱动用户交互。
  • 多账号隔离:为每个账号使用独立的
    partition
    值。
  • Chromium一致性:在平台配置中设置
    bundleCEF: true
    defaultRenderer: "cef"

Troubleshooting

故障排查

  • RPC calls fail unexpectedly:
    • Check whether the target webview is sandboxed (
      sandbox: true
      disables RPC).
    • Confirm shared RPC types match both bun and browser handlers.
  • Navigation blocks legitimate URLs:
    • Review
      setNavigationRules
      ordering; last match wins.
    • Keep
      ^*
      first only when you intentionally run strict allowlist mode.
  • Updater says no update:
    • Verify
      release.baseUrl
      and uploaded
      artifacts/
      naming (
      {channel}-{os}-{arch}-...
      ).
    • Confirm channel/build env alignment (
      canary
      vs
      stable
      ).
  • User sessions leak across accounts:
    • Use explicit per-account partitions and manage cookies via
      Session.fromPartition(...)
      .
  • Build hooks not running:
    • Ensure hook paths are correct and executable via Bun.
    • Inspect hook env vars (for example
      ELECTROBUN_BUILD_ENV
      ,
      ELECTROBUN_OS
      ,
      ELECTROBUN_ARCH
      ).
  • RPC调用意外失败:
    • 检查目标webview是否启用了沙箱模式(
      sandbox: true
      会禁用RPC)。
    • 确认主进程与浏览器进程的共享RPC类型定义一致。
  • 导航阻止了合法URL:
    • 检查
      setNavigationRules
      的规则顺序;最后匹配的规则生效。
    • 只有当你有意启用严格白名单模式时,才将
      ^*
      放在首位。
  • 更新器提示无可用更新:
    • 验证
      release.baseUrl
      和已上传的
      artifacts/
      命名格式(
      {channel}-{os}-{arch}-...
      )。
    • 确认渠道/构建环境一致(
      canary
      vs
      stable
      )。
  • 用户会话在多账号间泄露:
    • 为每个账号使用明确的独立分区,并通过
      Session.fromPartition(...)
      管理Cookie。
  • 构建钩子未运行:
    • 确保钩子路径正确且可通过Bun执行。
    • 检查钩子环境变量(例如
      ELECTROBUN_BUILD_ENV
      ELECTROBUN_OS
      ELECTROBUN_ARCH
      )。

Reference Files

参考文档

  • Build config, artifacts, and hooks: reference/build-config.md
  • BrowserWindow, BrowserView, and webview tag APIs: reference/window-and-webview.md
  • Menus, tray, events, updater, utils/session APIs: reference/platform-apis.md
  • 构建配置、产物与钩子:reference/build-config.md
  • BrowserWindow、BrowserView与webview标签API:reference/window-and-webview.md
  • 菜单、托盘、事件、更新器、工具类/会话API:reference/platform-apis.md