メインコンテンツにジャンプ

Build a Desktop App with Capacitor and Electron (2026)

CapacitorのアプリをElectronでデスクトップアプリに変える: セキュアシェルセットアップ、プラグイン戦略、macOS、Windows、Linux用のパッケージング、そしてライブアップデート。

著作権者

マーティン・ドナディュー

ライター

バレリア

レビュアー

ジョーダン

編集者

CapacitorとElectronでデスクトップアプリを構築する (2026)

デスクトップアプリをCapacitorアプリから作るには、同じウェブビルドをElectronシェルでラップする: メインプロセスがデスクトップアプリを開く、webDirElectronシェル内:メインプロセスがデスクトップアプリケーションを開きます。 BrowserWindow, a preload script that exposes a small desktop API, and electron-builder to produce installers for macOS, Windows, and Linux. Your UI and business logic stay shared with iOS and Android, and desktop-only features live in the Electron main process.

This guide covers the current state of Capacitor on Electron in 2026, a secure setup that works with Capacitor 8, how plugins behave, packaging and signing, and how to ship web updates without new installers.

2026年におけるCapacitorの現状

数年間、デフォルトの回答は @capacitor-community/electron, これはElectronをCapacitorCLIにプラットフォームとして接続するものでした。 そのプロジェクトは、READMEに記載されているように、現在は非メンテナンス状態となっています。 最後のnpmリリースである5.0.1は、2023年9月にリリースされました。 また、Capacitor 5.4以上が必要であり、Electron 26に対してビルドされていました。 ただし、Electronは多くのメジャーバージョンをリリースしており、最新の3つのメジャーバージョンだけがセキュリティ修正を受けます。

Capacitor 8アプリケーションでは、古いプロジェクトで使用することはできますが、比較は次のようになります。

アプローチ メリット デメリット
独自のElectronシェル(このガイド) 現在のElectron、完全な制御、追加の抽象化なし 約60行のmainとpreloadcodeを書く
@capacitor-community/electron 馴染みのあるもの cap コマンド メンテナンスされていない、古いCapacitorとElectronに固定

シェルアプローチは、実行する作業が思うほど多くありません。Capacitorはすでに静的Webビルドを生成するからです。Electronはそれを読み込むだけです。

Electronにおけるプラグインの動作

ElectronのレンダラーはChromiumなので、Capacitorアプリはブラウザで実行されるように動作します。Capacitorのコアはネイティブブリッジを検出できず、各プラグインのWeb実装にフォールバックします。

プラグインのタイプ Electronで動作するか? 何をするか
Web実装を持つプラグイン (Preferences、Share、Clipboard、多くのCapgoプラグイン) はい、Web版を使用 Webの動作をテスト
Web実装を持たないネイティブ専用プラグイン No, unimplemented として拒否します。 Electron のプレロード API を書きましょう。
純粋な JS ライブラリ Yes Nothing

Capacitor.getPlatform() Nothing 'web' 返します。 Capacitor.isNativePlatform() Nothing falseDesktopフラグを明示的にプレロードスクリプトから公開します。そうすることで、codeはクリーンにbranchできます。

.

  • Desktop フラグを明示的にプレロード スクリプトから公開しますので、Capacitor がクリーンに branch できます。 bun run build 前提条件があります。__CAPGO_KEEP_0__ アプリケーションが静的フォルダを出力する必要があります (これは、 webDir Capacitor capacitor.config.tsElectron dist Desktop www).
  • Bun と LTS の Node.js を使用してください。
  • macOSの場合、Apple Developer ID証明書が必要です。 Windowsの場合、code署名証明書が必要です。

Desktop

bun add -d electron electron-builder

Capacitor electron/ Electron

my-app/
  capacitor.config.ts
  dist/              # web build, shared with iOS and Android
  electron/
    main.ts
    preload.ts
  electron-builder.yml

Desktop

Capacitor file:// Electron

  1. Desktop Viteを使用して base: './' したので、ビルドされた index.html 参照 ./assets/... 代わりに /assets/....
  2. ルーティング。 デスクトップ用のデープリンク /settings ファイルとして存在しない。ハッシュルーティングを使用するか、ロード後にクライアント側でのみナビゲートするようにルーターを設定する index.html.
// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  base: './',
});

iOSとAndroidでも相対パスが機能するため、別のビルドが必要ない

ステップ 3: メインプロセスを書く

// electron/main.ts
import { app, BrowserWindow, ipcMain, shell } from 'electron';
import path from 'node:path';

const isDev = !app.isPackaged;

async function createWindow() {
  const win = new BrowserWindow({
    width: 1280,
    height: 800,
    minWidth: 800,
    minHeight: 600,
    show: false,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: true,
    },
  });

  win.once('ready-to-show', () => win.show());

  // Open external links in the default browser, never inside the app.
  // Only allow https: so a script cannot launch file: or other protocol handlers.
  win.webContents.setWindowOpenHandler(({ url }) => {
    try {
      if (new URL(url).protocol === 'https:') void shell.openExternal(url).catch(() => {});
    } catch {
      // invalid URL: ignore
    }
    return { action: 'deny' };
  });

  if (isDev) {
    await win.loadURL('http://localhost:5173');
    win.webContents.openDevTools({ mode: 'detach' });
  } else {
    await win.loadFile(path.join(__dirname, '..', '..', 'dist', 'index.html'));
  }
}

ipcMain.handle('desktop:get-version', () => app.getVersion());

app.whenReady().then(createWindow);

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) createWindow();
});

Keep contextIsolation: true, nodeIntegration: falseUIラベル sandbox: trueabout.astroのページについてのメッセージキー `about_how_step_label` (About How Step Label)で見ることができる。

Step 4: プリロードからデスクトップの小さなAPIを公開する

// electron/preload.ts
import { contextBridge, ipcRenderer } from 'electron';

contextBridge.exposeInMainWorld('desktop', {
  isElectron: true,
  platform: process.platform,
  getVersion: () => ipcRenderer.invoke('desktop:get-version') as Promise<string>,
});

ウェブ上でcodeを入力し、プラグインと同様に使用してください。

// src/desktop.ts
declare global {
  interface Window {
    desktop?: {
      isElectron: boolean;
      platform: string;
      getVersion: () => Promise<string>;
    };
  }
}

export const isDesktop = () => Boolean(window.desktop?.isElectron);

各デスクトップのネイティブ機能は、メインプロセスとプリロードの関数に分かれます。メインプロセスでは、レンダラーが信頼できないため、引数を検証します。 ipcMain.handle Step 5: ビルドと実行

Electronファイルをコンパイルするには、__CAPGO_KEEP_0__を使用します。プリロードはサンドボックス内で実行されるため、単一のCommonJSファイルとしてバンドルしてください。

ElectronファイルをBunでコンパイルする。プリロードはサンドボックス内で実行されるため、単一のCommonJSファイルとしてバンドルする。

{
  "main": "electron/dist/main.js",
  "scripts": {
    "build": "vite build",
    "electron:compile": "bun build electron/main.ts --outdir electron/dist --target node --format cjs --external electron && bun build electron/preload.ts --outdir electron/dist --target node --format cjs --external electron",
    "electron:dev": "bun run electron:compile && electron .",
    "electron:pack": "bun run build && bun run electron:compile && electron-builder"
  }
}

Step 6: electron-builderでインストーラーをパッケージ化するbun run devRun bun run electron:dev デスクトップウィンドウでホットリロードが可能です。

ステップ6:エレクトロンビルダーでパッケージインストーラーをインストール

# electron-builder.yml
appId: com.example.myapp
productName: My App
directories:
  output: release
files:
  - dist/**/*
  - electron/dist/**/*
  - package.json
mac:
  target: [dmg, zip]
  category: public.app-category.productivity
  hardenedRuntime: true
win:
  target: [nsis]
linux:
  target: [AppImage, deb]
  category: Utility

Run bun run electron:packelectron-builderは、実行しているOSに基づいてビルドします。CIでmacOS、Windows、Linuxのランナーを使用して、すべてのOSでビルドできます。

OS 共通のターゲット 署名
macOS .dmg, .zip 開発者ID証明書と認証のあるもの、またはゲートキーパーがアプリをブロックする
Windows NSIS .exe, MSI Code署名証明書を避けるため、スマートスクリーン警告を回避する
Linux AppImage、 .deb, .rpm オプション

Electronアプリはモバイルビルドよりも大きいのは、ChromiumとNode.jsを含むためです。インストーラーは80から150MBの範囲になります。ターゲットによっては異なります。

Step 7: Web更新を新しいインストーラーなしで配信

Most changes in a Capacitor app are web changes. On mobile you can ship those with Live Update. Capgo ライブアップデートライブアップデート @capgo/electron-updater でそれらを配信できます。デスクトップでは、 notifyAppReady().

bun add @capgo/electron-updater

同じモデルで同じ仕事をします: チャンネル、組み込まれたバンドル、ダウンロードしたバンドル、そして新しいバンドルが古いバンドルを呼び出す場合の自動ロールバック

// electron/main.ts (production branch)
import { ElectronUpdater, setupIPCHandlers, setupEventForwarding } from '@capgo/electron-updater';

const updater = new ElectronUpdater({
  appId: 'com.example.myapp',
  autoUpdate: true,
});

// inside createWindow(), instead of loading dist/index.html directly
const builtinPath = path.join(__dirname, '..', '..', 'dist', 'index.html');
await updater.initialize(win, builtinPath);
setupIPCHandlers(updater);
setupEventForwarding(updater, win);
await win.loadFile(updater.getCurrentBundlePath());

メインプロセスを更新してアップデータがバンドルを読み込むバンドルを選択できるようにします:

// electron/preload.ts (next to the desktop API)
import { exposeUpdaterAPI } from '@capgo/electron-updater/preload';

exposeUpdaterAPI();

アップデータブリッジを同じプリロードファイルに追加します:

import { isDesktop } from './desktop';

if (isDesktop()) {
  const { requireUpdater } = await import('@capgo/electron-updater/renderer');
  await requireUpdater().notifyAppReady();
}

モバイルで使用している同じCLIで新しいバンドルをアップロードしてください。

bun run build
bunx @capgo/cli@latest bundle upload --channel=production

同じ ライブアップデート パスをカバーし、 electron-updater プラグインのページ と ドキュメント すべてのオプションをカバーする

トラブルシューティング

パッケージされたアプリで白いウィンドウが表示される アセットは絶対パスを使用している。セット base: './' パッケージされたアプリでDevToolsを開いて404エラーを確認する file:///assets/....

ルートが白いページを表示する ルータがディスクからロードしようとした /route ハッシュルーティングをデスクトップに切り替える

require is not defined またはプレロードエラー。 サンドボックス化されたプレロードは実行時には任意のパッケージをロードできません。1つのファイルにバンドルしてください。上記のコンパイルスクリプトと同じように。

プラグインコールは「Web上では実装されていません」というエラーで拒否されます。 そのプラグインにはWeb上での実装がないので、メインプロセスでIPCハンドラーを追加し、そこから呼び出してください。 window.desktop.

macOSはアプリが損傷したものまたは不明の開発者から来たものであると表示します。 アプリは署名されていないし、認証されていないので、electron-builderで開発者ID証明書と認証を設定してください。

アップデートはインストール直後に戻ります。 notifyAppReady() タイムアウト(10秒でデフォルト)内に呼び出されていませんでした。アプリ起動時に早く呼び出してください。

まとめ

専用のCapacitorプラットフォームパッケージが必要ないので、デスクトップにアクセスできます。短いElectronメインプロセス、プレロードで型付きのAPIを公開する、相対的なアセットパス、electron-builderでインストーラーを作成できます。Webビルドから3つのオペレーティングシステムのインストーラーを作成できます。追加してください。 @capgo/electron-updater デスクトップアプリはiOSとAndroidビルドと同じlive updateワークフローを取得します。デスクトップランタイムを選択する場合は、ElectronとTauriの比較を読んでください。 ElectronとTauriの比較.

Capacitor アプリ用の即時更新

ウェブ層のバグが生じた場合、Capgo を通じて修正を配信するのではなく、数日間待ってアプリストアの承認を待つのではなく、ユーザーはバックグラウンドで更新を受け取り、ネイティブの変更は通常のレビュー経路に従う

最新のブログ記事

Capgoは、プロフェッショナルなモバイルアプリを作成するために必要な最良の洞察を提供します。