electrobun-platform
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseElectrobun Cross-Platform Reference
Electrobun 跨平台参考
Platform Support Matrix
平台支持矩阵
| Platform | OS value | Arch | Status | Default Webview |
|---|---|---|---|---|
| macOS ARM64 | | | Stable | WKWebView |
| macOS Intel | | | Stable | WKWebView |
| Windows x64 | | | Stable | WebView2 (Edge) |
| Windows ARM64 | | | Via emulation | Runs x64 binary |
| Linux x64 | | | Stable | GTKWebKit |
| Linux ARM64 | | | Stable | GTKWebKit |
Build each platform on its native OS — no cross-compilation.
| 平台 | OS 值 | 架构 | 状态 | 默认 Webview |
|---|---|---|---|---|
| macOS ARM64 | | | 稳定 | WKWebView |
| macOS Intel | | | 稳定 | WKWebView |
| Windows x64 | | | 稳定 | WebView2 (Edge) |
| Windows ARM64 | | | 通过模拟 | 运行 x64 二进制文件 |
| Linux x64 | | | 稳定 | GTKWebKit |
| Linux ARM64 | | | 稳定 | GTKWebKit |
每个平台都应在其原生 OS 上构建——不支持交叉编译。
Linux — Always Bundle CEF
Linux — 始终捆绑 CEF
GTKWebKit has severe limitations:
- No webview layering (no overlapping webviews)
- No masking
- No compositing
<electrobun-webview> - Renderer mixing not supported — all webviews must use same renderer
For anything beyond a single-webview app on Linux:
typescript
// electrobun.config.ts
build: {
linux: { bundleCEF: true, defaultRenderer: 'cef' },
}GTKWebKit 存在严重限制:
- 不支持 Webview 分层(无法重叠 Webview)
- 不支持蒙版
- 不支持 合成
<electrobun-webview> - 不支持混用 Renderer——所有 Webview 必须使用同一个 Renderer
对于 Linux 上单 Webview 应用之外的任何场景:
typescript
// electrobun.config.ts
build: {
linux: { bundleCEF: true, defaultRenderer: 'cef' },
}Windows — Console Output
Windows — 控制台输出
Production Windows builds use the GUI subsystem — no console for end users.
cmd
set ELECTROBUN_CONSOLE=1
.\MyApp.exeHas no effect on macOS or Linux. Dev builds auto-attach a console.
生产环境中的 Windows 构建使用 GUI 子系统——最终用户不会看到控制台。
cmd
set ELECTROBUN_CONSOLE=1
.\MyApp.exe对 macOS 或 Linux 无效。开发构建会自动附加控制台。
Webview Hidden/Passthrough Behavior
Webview 隐藏/穿透行为
typescript
// macOS: hidden and passthrough are INDEPENDENT
webviewSetHidden(webviewId, true); // hidden, still intercepts clicks
webviewSetPassthrough(webviewId, true); // separate call for click-through
// Windows & Linux: hidden = hidden + passthrough automatically
webviewSetHidden(webviewId, true); // hidden AND clicks pass through
// webviewSetPassthrough() is a no-op on Windows/Linuxtypescript
// macOS: hidden and passthrough are INDEPENDENT
webviewSetHidden(webviewId, true); // hidden, still intercepts clicks
webviewSetPassthrough(webviewId, true); // separate call for click-through
// Windows & Linux: hidden = hidden + passthrough automatically
webviewSetHidden(webviewId, true); // hidden AND clicks pass through
// webviewSetPassthrough() is a no-op on Windows/Linux<electrobun-webview>
HTML Tag (OOPIF)
<electrobun-webview><electrobun-webview>
HTML 标签(OOPIF)
<electrobun-webview>Process-isolated "super iframes" — positioned by DOM, rendered natively.
Requires CEF on Linux.
html
<electrobun-webview
src="https://example.com"
width="100%"
height="400px"
renderer="cef">
</electrobun-webview>Access from bun: includes OOPIFs.
BrowserView.getAll()进程隔离的“super iframes”——由 DOM 定位,以原生方式渲染。
Linux 上需要 CEF。
html
<electrobun-webview
src="https://example.com"
width="100%"
height="400px"
renderer="cef">
</electrobun-webview>从 bun 访问时: 包含 OOPIF。
BrowserView.getAll()CEF Version Override
CEF 版本覆盖
typescript
build: {
cefVersion: '144.0.11+ge135be2+chromium-144.0.7559.97',
}Same major = safe. Adjacent major = usually fine. Distant majors = higher risk.
typescript
build: {
cefVersion: '144.0.11+ge135be2+chromium-144.0.7559.97',
}相同主版本号 = 安全。相邻主版本号 = 通常没问题。相距较远的主版本号 = 风险更高。
Chromium Flags (CEF only)
Chromium 标志(仅限 CEF)
typescript
build: {
mac: {
bundleCEF: true,
chromiumFlags: {
'show-paint-rects': true,
'user-agent': 'MyApp/1.0',
'disable-web-security': true,
},
},
}typescript
build: {
mac: {
bundleCEF: true,
chromiumFlags: {
'show-paint-rects': true,
'user-agent': 'MyApp/1.0',
'disable-web-security': true,
},
},
}Per-Window Renderer Override
逐窗口 Renderer 覆盖
typescript
// Override defaultRenderer per window
const win = new BrowserWindow({ url: '...', renderer: 'native' });
const cefWin = new BrowserWindow({ url: '...', renderer: 'cef' });Mixing allowed on macOS and Windows. Not allowed on Linux.
typescript
// Override defaultRenderer per window
const win = new BrowserWindow({ url: '...', renderer: 'native' });
const cefWin = new BrowserWindow({ url: '...', renderer: 'cef' });macOS 和 Windows 允许混用。Linux 不允许混用。
Events API
事件 API
typescript
import Electrobun from 'electrobun/bun';
// App lifecycle
Electrobun.events.on('before-quit', (e) => {
if (hasUnsavedChanges()) e.response = { allow: false }; // cancel quit
});
Electrobun.events.on('open-url', (e) => {
const url = new URL(e.data.url); // macOS URL scheme deep links
});
// Window events (global — all windows)
Electrobun.events.on('close', (e) => { /* e.data.id */ });
Electrobun.events.on('resize', (e) => { /* e.data.id, width, height */ });
Electrobun.events.on('move', (e) => { /* e.data.id, x, y */ });
Electrobun.events.on('blur', (e) => { /* e.data.id */ });
Electrobun.events.on('focus', (e) => { /* e.data.id */ });
// Menu / tray
Electrobun.events.on('application-menu-clicked', (e) => { /* e.data.action */ });
Electrobun.events.on('context-menu-clicked', (e) => { /* e.data.action, data */ });
Electrobun.events.on('tray-menu-clicked', (e) => { /* e.data.action */ });Quit trigger sources: dock icon, Cmd+Q, Ctrl+C, SIGTERM, window close, , — all route through .
Utils.quit()process.exit()before-quitLinux caveat: system-initiated quit paths (window-manager close, taskbar) may bypass . and are reliable.
before-quitUtils.quit()process.exit()typescript
import Electrobun from 'electrobun/bun';
// App lifecycle
Electrobun.events.on('before-quit', (e) => {
if (hasUnsavedChanges()) e.response = { allow: false }; // cancel quit
});
Electrobun.events.on('open-url', (e) => {
const url = new URL(e.data.url); // macOS URL scheme deep links
});
// Window events (global — all windows)
Electrobun.events.on('close', (e) => { /* e.data.id */ });
Electrobun.events.on('resize', (e) => { /* e.data.id, width, height */ });
Electrobun.events.on('move', (e) => { /* e.data.id, x, y */ });
Electrobun.events.on('blur', (e) => { /* e.data.id */ });
Electrobun.events.on('focus', (e) => { /* e.data.id */ });
// Menu / tray
Electrobun.events.on('application-menu-clicked', (e) => { /* e.data.action */ });
Electrobun.events.on('context-menu-clicked', (e) => { /* e.data.action, data */ });
Electrobun.events.on('tray-menu-clicked', (e) => { /* e.data.action */ });退出触发来源:Dock 图标、Cmd+Q、Ctrl+C、SIGTERM、窗口关闭、、——所有路径都会进入 。
Utils.quit()process.exit()before-quitLinux 注意事项:由系统触发的退出路径(窗口管理器关闭、任务栏)可能会绕过 。 和 可靠有效。
before-quitUtils.quit()process.exit()URL Schemes / Deep Linking
URL Schemes / 深层链接
macOS only. App must be in or .
/Applications~/Applicationstypescript
// electrobun.config.ts
app: { urlSchemes: ['myapp', 'myapp-dev'] }
// src/bun/index.ts
Electrobun.events.on('open-url', (e) => {
const url = new URL(e.data.url);
if (url.pathname.startsWith('/auth')) { /* handle */ }
});Windows/Linux URL schemes not yet supported.
仅支持 macOS。应用必须位于 或 。
/Applications~/Applicationstypescript
// electrobun.config.ts
app: { urlSchemes: ['myapp', 'myapp-dev'] }
// src/bun/index.ts
Electrobun.events.on('open-url', (e) => {
const url = new URL(e.data.url);
if (url.pathname.startsWith('/auth')) { /* handle */ }
});Windows/Linux 尚不支持 URL Schemes。
Security Checklist
安全检查清单
- on any BrowserView loading untrusted URLs — disables RPC, events still work
sandbox: true - to allowlist permitted navigation targets; last match wins
setNavigationRules - Never expose APIs to sandboxed views — route through RPC with validation
electrobun/bun - Use separate values per account for session isolation
partition - Prefer over
views://for local assetsfile://
- 对任何加载不受信任 URL 的 BrowserView 设置 ——这会禁用 RPC,但事件仍可正常工作
sandbox: true - 使用 将允许的导航目标加入白名单;最后一次匹配优先
setNavigationRules - 切勿向沙箱化视图暴露 API——应通过带验证的 RPC 进行路由
electrobun/bun - 为每个账户使用不同的 值,以隔离会话
partition - 对于本地资源,优先使用 而非
views://file://
Code Signing (macOS)
代码签名(macOS)
One-Time Setup
一次性设置
- Install full Xcode from App Store (not CLI tools alone — avoids expired cert issues)
- Xcode → Settings → Accounts → add Apple ID → Manage Certificates → → Developer ID Application
+ - Apple Developer Portal: Identifiers → register bundle ID
- account.apple.com: App Specific Passwords → create one
- 从 App Store 安装完整的 Xcode(不能只安装 CLI 工具——可避免证书过期问题)
- Xcode → Settings → Accounts → 添加 Apple ID → Manage Certificates → → Developer ID Application
+ - Apple Developer Portal:Identifiers → 注册 bundle ID
- account.apple.com:App Specific Passwords → 创建一个
Required Env Vars
必需环境变量
bash
export ELECTROBUN_DEVELOPER_ID="My Corp Inc. (BGU899NB8T)"
export ELECTROBUN_TEAMID="BGU899NB8T"
export ELECTROBUN_APPLEID="you@example.com"
export ELECTROBUN_APPLEIDPASS="xxxx-xxxx-xxxx-xxxx"Unsigned apps show "damaged and can't be opened" — users fix with:
bash
xattr -cr /Applications/YourApp.appbash
export ELECTROBUN_DEVELOPER_ID="My Corp Inc. (BGU899NB8T)"
export ELECTROBUN_TEAMID="BGU899NB8T"
export ELECTROBUN_APPLEID="you@example.com"
export ELECTROBUN_APPLEIDPASS="xxxx-xxxx-xxxx-xxxx"未签名的应用会显示“已损坏且无法打开”——用户可以使用以下命令修复:
bash
xattr -cr /Applications/YourApp.appEntitlements
Entitlements(权限声明)
typescript
build: {
mac: {
entitlements: {
'com.apple.security.device.camera': 'Needed for video',
'com.apple.security.device.microphone': 'Needed for audio',
}
}
}typescript
build: {
mac: {
entitlements: {
'com.apple.security.device.camera': 'Needed for video',
'com.apple.security.device.microphone': 'Needed for audio',
}
}
}Application Icons
应用程序图标
typescript
build: {
mac: { icons: 'icon.iconset' },
// icon.iconset/ must contain icon_{16,32,64,128,256,512}x{same}[@2x].png
win: { icon: 'icon.iconset/icon_256x256.png' }, // .ico or .png, auto-converted
linux: { icon: 'icon.iconset/icon_256x256.png' }, // 256x256+ .png
}Reuse PNGs from the macOS iconset for Windows/Linux — no separate files needed.
typescript
build: {
mac: { icons: 'icon.iconset' },
// icon.iconset/ must contain icon_{16,32,64,128,256,512}x{same}[@2x].png
win: { icon: 'icon.iconset/icon_256x256.png' }, // .ico or .png, auto-converted
linux: { icon: 'icon.iconset/icon_256x256.png' }, // 256x256+ .png
}可复用 macOS iconset 中的 PNG 文件作为 Windows/Linux 图标——无需单独准备文件。
Artifact Naming Convention
制品命名规范
Artifacts use prefix. Stable omits the channel. App name spaces stripped.
{channel}-{os}-{arch}-canary-macos-arm64-MyApp-canary.dmg
canary-macos-arm64-MyApp-canary.app.tar.zst
canary-macos-arm64-{prevHash}.patch
canary-win-x64-MyApp-Setup-canary.zip
canary-win-x64-MyApp-canary.tar.zst
canary-linux-x64-MyAppSetup-canary.tar.gz
stable-macos-arm64-MyApp.dmg ← no "stable" in name on stable channelKeep old patches on your static host — users >1 version behind auto-fall back to full .
.tar.zst制品使用 前缀。Stable 渠道会省略渠道名。应用名称中的空格会被移除。
{channel}-{os}-{arch}-canary-macos-arm64-MyApp-canary.dmg
canary-macos-arm64-MyApp-canary.app.tar.zst
canary-macos-arm64-{prevHash}.patch
canary-win-x64-MyApp-Setup-canary.zip
canary-win-x64-MyApp-canary.tar.zst
canary-linux-x64-MyAppSetup-canary.tar.gz
stable-macos-arm64-MyApp.dmg ← no "stable" in name on stable channel请在静态托管上保留旧补丁——落后超过 1 个版本的用户会自动回退到完整的 文件。
.tar.zstRelease Hosting
发布托管
Static file host — no server required: S3, Cloudflare R2, GCS, GitHub Releases.
typescript
release: {
baseUrl: 'https://storage.googleapis.com/mybucket/myapp/',
// GitHub Releases:
// baseUrl: 'https://github.com/ORG/REPO/releases/latest/download',
}GitHub Releases limitation: skips prereleases. Stable works; canary auto-updates will NOT — use R2/S3 for canary channel.
/releases/latest/download静态文件托管——无需服务器:S3、Cloudflare R2、GCS、GitHub Releases。
typescript
release: {
baseUrl: 'https://storage.googleapis.com/mybucket/myapp/',
// GitHub Releases:
// baseUrl: 'https://github.com/ORG/REPO/releases/latest/download',
}GitHub Releases 限制: 会跳过预发布版本。Stable 渠道可用;但 Canary 自动更新将不可用——Canary 渠道请使用 R2/S3。
/releases/latest/downloadCI Build Matrix (GitHub Actions)
CI 构建矩阵(GitHub Actions)
Each platform must build on its own native runner:
yaml
jobs:
build-macos-arm64:
runs-on: macos-14 # Apple Silicon
build-macos-x64:
runs-on: macos-13 # Intel
build-windows:
runs-on: windows-latest
build-linux:
runs-on: ubuntu-latest每个平台都必须在各自的原生 runner 上构建:
yaml
jobs:
build-macos-arm64:
runs-on: macos-14 # Apple Silicon
build-macos-x64:
runs-on: macos-13 # Intel
build-windows:
runs-on: windows-latest
build-linux:
runs-on: ubuntu-latestEach job:
Each job:
uses: actions/checkout@v4
uses: actions/checkout@v4
uses: oven-sh/setup-bun@v2
uses: oven-sh/setup-bun@v2
run: bun install
run: bun install
run: electrobun build --env=stable
run: electrobun build --env=stable
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v1
with: files: artifacts/*
with: files: artifacts/*
Tag naming convention: tags containing `-canary` → canary build; all others → stable.
标签命名规范:包含 `-canary` 的标签 → Canary 构建;其他所有标签 → Stable。ASAR Packaging
ASAR 打包
typescript
build: {
useAsar: true,
asarUnpack: ['*.node', '*.dll', '*.dylib', '*.so', 'data/large/**/*'],
}Packs app resources into . Unpacked files → . Benefits: faster I/O, code obfuscation via randomized temp paths.
app.asarapp.asar.unpacked/typescript
build: {
useAsar: true,
asarUnpack: ['*.node', '*.dll', '*.dylib', '*.so', 'data/large/**/*'],
}将应用资源打包到 中。解包后的文件 → 。优点:I/O 更快;通过随机临时路径实现代码混淆。
app.asarapp.asar.unpacked/Common Pitfalls
常见问题
| Issue | Fix |
|---|---|
| Linux webview layering broken | |
| Canary auto-update not working | GitHub |
| "damaged and can't be opened" macOS | Enable |
| Code signing cert errors | Install full Xcode from App Store, not just CLI tools |
| RPC type mismatch at runtime | Confirm shared type file is imported by both sides |
| Sandbox webview + RPC silent failure | |
| Windows no console output | Set |
| URL schemes not registering | App must be in |
| Cross-compilation attempt | Each platform must build on its own native OS |
| Linux renderer mixing | All webviews must use the same renderer on Linux |
| Old patches missing | Keep all patch files on static host for sequential upgrades |
| System-initiated quits may bypass it; |
| Notarize + codesign disabled for speed | Turn off during rapid debug cycles, re-enable for release |
| 问题 | 修复方法 |
|---|---|
| Linux Webview 分层损坏 | |
| Canary 自动更新不工作 | GitHub |
| macOS 显示“已损坏且无法打开” | 启用 |
| 代码签名证书错误 | 从 App Store 安装完整 Xcode,而不只是 CLI 工具 |
| 运行时 RPC 类型不匹配 | 确认共享类型文件已由两端导入 |
| 沙箱 Webview + RPC 静默失败 | |
| Windows 无控制台输出 | 设置 |
| URL Schemes 无法注册 | 应用必须位于 |
| 尝试交叉编译 | 每个平台都必须在自己的原生 OS 上构建 |
| Linux 上混用 Renderer | 所有 Webview 必须使用同一个 Renderer |
| 缺少旧补丁 | 在静态托管上保留所有补丁文件,以支持顺序升级 |
| 系统触发的退出会绕过它; |
| 为提高调试速度而禁用 Notarize + codesign | 在快速调试阶段将其关闭,发布前重新启用 |