Zum Hauptinhalt springen

Build eine Desktop-Anwendung mit Capacitor und Electron (2026)

Machen Sie aus Ihrem Capacitor-App ein Desktop-App mit Electron: Sicherheitseinstellungen für die Shell, Plugin-Strategie, Verpackung für macOS, Windows, Linux und Live-Updates.

Artikel-Kredits

Martin Donadieu

Schreiber

Valeria

Rezensent

Jordan

Redakteur

Erstellen Sie eine Desktop-Anwendung mit Capacitor und Electron (2026)

Um eine Desktop-Anwendung aus einer Capacitor-Anwendung zu erstellen, umhüllen Sie die gleiche Web-Build.webDir) in einer Electron-Hülle: einen Hauptprozess, der eine BrowserWindow, einen Vorkommando, der einen kleinen Desktop-API offenlegt, und electron-builder, um Installationsprogramme für macOS, Windows und Linux zu erstellen. Ihre Benutzeroberfläche und Geschäftslogik bleiben mit iOS und Android geteilt, und Desktop-spezifische Funktionen leben im Electron-Hauptprozess.

Diese Anleitung behandelt den aktuellen Stand von Capacitor auf Electron im Jahr 2026, eine sichere Konfiguration, die mit Capacitor 8 funktioniert, wie Plugins verhalten sich, Verpacken und Signieren, und wie Web-Updates ohne neue Installationsprogramme verschickt werden können.

Der Stand von Capacitor auf Electron im Jahr 2026

Für Jahre war die Standardantwort @capacitor-community/electron, die Electron in das Capacitor CLI als Plattform einband. Das Projekt ist jetzt als nicht mehr unterstützt in seinem eigenen README markiert. Sein letzter npm-Release, 5.0.1, wurde im September 2023 veröffentlicht, erfordert Capacitor 5.4 oder später und wurde gegen Electron 26 aufgebaut. Electron hat seitdem viele wichtige Versionen veröffentlicht, und nur die letzten drei Majors erhalten Sicherheitsfixes.

Sie können es immer noch auf alten Projekten verwenden, aber für eine Capacitor 8-Anwendung sieht die Vergleichsliste so aus:

Ansatz Vorteile Nachteile
Ihr eigener Electron-Shell (diese Anleitung) Aktuelles Electron, volle Kontrolle, keine zusätzliche Abstraktion Sie schreiben etwa 60 Zeilen von Haupt- und Vorladungscode code
@capacitor-community/electron Vertraut cap Befehle Nicht mehr unterstützt, auf altes Capacitor und Electron festgelegt

Die Shell-Methode ist weniger Arbeit als es klingt, weil Capacitor bereits eine statische Web-Anwendung erstellt. Electron muss sie nur laden.

Wie Plugins in Electron verhalten

Electrons Renderer ist Chromium, daher läuft Ihre Capacitor-Anwendung dort wie in einem Browser. Capacitor's Kern erkennt keine native Brücke und fällt auf die Web-Implementierung jeder Plugin zurück.

Plugin-Typ Funktioniert in Electron? Was tun
Plugin mit Web-Implementierung (Einstellungen, Teilen, Auskopieren, viele Capgo-Plugins) Ja, mit der Web-Version Testen Sie das Web-Verhalten
Nur-native-Plugin (keine Web-Implementierung) No, wird als nicht implementiert abgelehnt Schreiben Sie ein Electron-Äquivalent hinter einem API-Vorladepreload
Reine JS-Bibliotheken Ja Nein

Capacitor.getPlatform() keine Rückkehr 'web' erfolgt in dieser Konfiguration und Capacitor.isNativePlatform() keine Rückkehr false. Wir werden einen expliziten Desktop-Flag aus dem Vorladepreload-Script ausgeben, so dass Ihr code sauber abzweigen kann

Voraussetzungen

  • Eine Capacitor-Anwendung, deren bun run build eine statische Ordner (den webDir auf capacitor.config.ts, oft dist oder www).
  • Bun und ein aktuelles LTS Node.js, da Electron-Tooling noch auf Node läuft.
  • Für die macOS-Distribution ist ein Apple-Entwickler-ID-Zertifikat erforderlich. Für Windows ein code-Zertifikat zur Signierung.

Schritt 1: Installieren Sie Electron und den Packager

bun add -d electron electron-builder

Hinzufügen electron/ Ordner im Projektroot:

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

Schritt 2: Laden Sie die Web-Ausgabe von der Festplatte

Protokoll in der Produktion. Zwei Einstellungen sind wichtig: file:// Relative Pfadangaben zu Assets.

  1. __CAPGO_KEEP_0__ Mit Vite, setze base: './' so die gebauten index.html Referenzen ./assets/... anstatt /assets/....
  2. Routing. Tiefe Links wie /settings existieren nicht als Dateien. Verwenden Sie Hash-Routing für die Desktop-Build, oder stellen Sie sicher, dass Ihr Router nur kundenseitig navigiert, nachdem er geladen wurde index.html.
// vite.config.ts
import { defineConfig } from 'vite';

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

Relative Pfade funktionieren auch auf iOS und Android, daher benötigen Sie keine separate Build.

Schritt 3: Schreiben Sie den Hauptprozess

// 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();
});

Behalten Sie contextIsolation: true, nodeIntegration: false, und sandbox: true. Ihr Web-App kann Drittanbieter-Scripts laden, und keines davon sollte Zugriff auf Node.js haben.

Schritt 4: Expose eine kleine Desktop-API aus der Vorkomprimierung

// 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>,
});

Tippen Sie es in Ihrem Web-code ein und verwenden Sie es auf die gleiche Weise wie ein Plugin:

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

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

Jedes native-only-Funktion, das Sie auf dem Desktop benötigen, wird zu einem ipcMain.handle einen in der Hauptprozess und eine Funktion in der Vorkomprimierung. Überprüfen Sie die Argumente im Hauptprozess, da der Renderer unvertrauenswürdig ist.

Schritt 5: Erstellen und ausführen

Kompilieren Sie die Electron-Dateien mit Bun. Die Vorkomprimierung läuft sandboxed, also bündeln Sie sie als ein einzelnes CommonJS-File ein:

{
  "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"
  }
}

Zu Entwicklungszwecken starten Sie Ihren Dev-Server in einem Terminal (bun run dev) und bun run electron:dev in einem anderen. Sie erhalten eine Hot-Reload im Desktop-Fenster.

Schritt 6: Paketieren von Installern mit electron-builder

# 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

Laufen bun run electron:pack.electron-builder baut für das Betriebssystem, auf dem es ausgeführt wird. Verwenden Sie eine Matrix aus macOS, Windows- und Linux-Runnern in CI, um alle drei zu produzieren.

OS Gemeinsame Ziele Signierung
macOS .dmg, .zip Entwickler-ID-Zertifikat plus Notarisation, oder Gatekeeper blockiert die Anwendung
Windows NSIS .exe, MSI Code Signierungszertifikat, um SmartScreen-Warnungen zu vermeiden
Linux AppImage, .deb, .rpm Optional

Elektron-Apps sind größer als mobile Builds, da sie Chromium und Node.js enthalten. Installationsdateien liegen je nach Zielgruppe zwischen 80 und 150 MB.

Schritt 7: Schicken Sie Web-Updates ohne neue Installationsdateien

Die meisten Änderungen in einer Capacitor-Anwendung sind Web-Änderungen. Auf dem Mobilgerät können Sie diese mit Capgo Live-Updates__CAPGO_KEEP_0__-Live-Updates @capgo/electron-updater macht dasselbe mit demselben Modell: Kanäle, ein eingebauter Bundle, heruntergeladene Bundle und automatische Rollover, wenn das neue Bundle nicht funktioniert notifyAppReady().

bun add @capgo/electron-updater

Aktualisieren Sie den Hauptprozess, damit der Updater die zu ladende Bundle auswählen kann:

// 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());

Fügen Sie die Updater-Brücke in das gleiche Präloader-File ein:

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

exposeUpdaterAPI();

Und bestätige eine gesunde Startphase aus der Web-Anwendung, nur auf dem Desktop:

import { isDesktop } from './desktop';

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

Upload a new bundle with the same CLI you use for mobile:

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

Web updates cannot change Electron itself, the main process, or the preload. For those, ship a new installer with a binary auto-updater. Our guide on Elektron-aktualisierungen covers diese Pfade ab, und die electron-updater-Plugin-Seite und docs deckt alle Optionen ab.

Schwierigkeiten

Ein leerer Fenster im verpackten App. Assets verwenden absolute Pfade. Setze base: './' und neu erstellen. Öffnen Sie die DevTools im verpackten App, um 404s zu bestätigen. file:///assets/....

Routen zeigen eine leere Seite nach dem Neuladen. Der Router versuchte, zu laden /route Die Routen zeigten ein leeres Fenster nach dem Neuladen.

require is not defined oder Fehler vor dem Laden. Der sandboxierte Vorkomprimierung kann keine beliebigen Pakete zur Laufzeit laden. Komprimieren Sie es in eine Datei, wie im obigen Kompilierungsskript.

Ein Pluginaufruf wird mit „nicht implementiert auf Web“ abgelehnt. Das Plugin hat keine Web-Implementierung. Fügen Sie einen IPC-Handler in der Hauptprozess und rufen Sie ihn über window.desktop.

macOS sagt, dass die Anwendung beschädigt oder von einem unbekannten Entwickler stammt. Die Anwendung ist nicht signiert und nicht notarisiert. Konfigurieren Sie ein Entwickler-ID-Zertifikat und eine Notarisation in electron-builder.

Updates rollen sich sofort nach der Installation zurück. notifyAppReady() war nicht innerhalb der Zeitüberschreitung (10 Sekunden standardmäßig) aufgerufen. Rufen Sie es frühzeitig in Ihrem Anwendungsstart auf.

Abschluss

Sie benötigen kein spezielles Capacitor Plattformpaket, um auf den Desktop zu gelangen. Ein kurzer Electron-Hauptprozess, eine Vorkomprimierung, die einen API-Typ ausgibt, relative Asset-Pfade und electron-builder geben Ihnen Installationsprogramme für alle drei Betriebssysteme aus einer einzigen Web-Build. Fügen Sie @capgo/electron-updater und die Desktop-Anwendung erhält das gleiche live update-Workflow wie Ihre iOS- und Android-Builds. Wenn Sie noch immer eine Desktop-Laufzeitumgebung wählen, lesen Sie unseren Vergleich zwischen Electron und Tauri.

Live-Updates für Capacitor-Anwendungen

Wenn ein Web-Schicht-Bug live ist, schicken Sie die Reparatur über Capgo anstatt Tage zu warten, bis das App-Store-Update genehmigt ist. Die Benutzer erhalten das Update im Hintergrund, während native Änderungen im normalen Review-Prozess bleiben.

Neueste aus unserem Blog

Capgo bietet Ihnen die besten Erkenntnisse, die Sie benötigen, um eine wirklich professionelle Mobilanwendung zu erstellen.