TL;DR
TypeScript だけでメインプロセスも UI も書けるデスクトップアプリのフレームワーク。Bun と OS ネイティブの WebView を使い、バンドルサイズと起動時間を小さく抑えている。
なぜ必要か
既存の選択肢にはそれぞれ問題がある。Electron はバンドルサイズが 150MB ほどあり、起動が遅い。Tauri では、学習コストの高い Rust を学ばなければならない。ネイティブで書くと、プラットフォームごとにコードが分かれて複雑になる。
Electrobun のバンドルサイズは約 14MB で、Electron より 90% 小さい。起動時間は 50ms 未満(Electron は 2〜5 秒)で、アプリを更新するときにユーザがダウンロードするサイズは 14KB ほどで済む。
仕組み
ウィンドウ管理やシステムトレイ(macOS のメニューバーに出るアイコンなど)は、C++ と Objective-C によるネイティブバインディングで実装されている。TypeScript は Bun ランタイムで動くので、Node.js や V8 のオーバーヘッドがない。
UI の描画には OS ネイティブの WebView(Windows では Edge WebView2、macOS では WebKit)を使う。Chromium(CEF)を同梱することもできる。React、Vue、Svelte などの Web フレームワークにも対応している。
アップデートの差分パッチは、Zig で SIMD 最適化した BSDIFF で作るので、KB 単位で配布できる。
公式は、開発に Co(lab) という独自の IDE を勧めているようだ。
例
bunx electrobun init を実行すると、テンプレートを選べる。
🚀 Welcome to Electrobun!
Available templates:
1. photo-booth
2. svelte
3. hello-world
4. multitab-browser
5. react-tailwind-viteSvelte を選ぶと、次のディレクトリ構成になる。
.
├── bun.lock
├── electrobun.config.ts
├── llms.txt
├── package.json
├── README.md
├── src
│ ├── bun
│ │ └── index.ts
│ └── mainview
│ ├── app.css
│ ├── App.svelte
│ ├── index.html
│ └── main.ts
├── svelte.config.js
├── tsconfig.json
└── vite.config.ts
src/bun/ にメインプロセスを、src/mainview/ に UI を置く。メインプロセスからは Bun API を呼び出す。Electrobun の設定は electrobun.config.ts に書く。LLM 向けのテキストファイル llms.txt も入っている。
開発サーバは bun dev で立ち上げ、HMR を使うなら bun run dev:hmr を使う。ビルドは bun run build か bun run build:prod で行う。
src/mainview/App.svelte を書き直して、簡単な Web ブラウザを作った(electrobun-simple-browser)。<electrobun-webview> は、WebView を配置するための Custom Element である。
<script lang="ts">
import type { WebviewTagElement } from "electrobun/view";
import { onMount } from "svelte";
const initialUrl = "https://electrobun.dev";
let inputUrl = $state(initialUrl);
let electroBunWebViewElement: WebviewTagElement;
const loadPage = () => {
electroBunWebViewElement.loadURL(inputUrl);
};
const goBack = () => {
electroBunWebViewElement.goBack();
};
const goForward = () => {
electroBunWebViewElement.goForward();
};
onMount(() => {
electroBunWebViewElement.loadURL(inputUrl);
});
</script>
<main>
<h1>My Web Browser</h1>
<input type="text" placeholder="Enter URL" bind:value={inputUrl} />
<button onclick={loadPage}>Go</button>
<button onclick={goBack}>Back</button>
<button onclick={goForward}>Forward</button>
<electrobun-webview
bind:this={electroBunWebViewElement}
class="webview"
width="100%"
height="100%"
></electrobun-webview>
</main>自分の理解
テンプレートに Svelte があるのはうれしい。HMR の有無で別のコマンドが割り当てられているのも面白い。