Skip to content

Kapitel 3: Electron-Kernarchitektur und Prozesse

In diesem Kapitel lernen Sie die Architektur von Electron kennen - das wichtigste Konzept für Einsteiger.

3.1 Electron-Kernarchitektur

Architektur-Überblick

Electron besteht aus zwei Hauptprozessen:

┌─────────────────────────────────────────┐
│           Electron App                  │
│                                         │
│  ┌─────────────────────────────────┐   │
│  │     Hauptprozess (Main)         │   │
│  │  - App-Lebenszyklus            │   │
│  │  - Fensterverwaltung            │   │
│  │  - Native APIs                  │   │
│  │  - Node.js Zugriff             │   │
│  └──────────┬──────────────────────┘   │
│             │ IPC                       │
│  ┌──────────▼──────────────────────┐   │
│  │   Renderer-Prozess (Renderer)   │   │
│  │  - UI-Rendering (Chromium)      │   │
│  │  - Web-Seiten                   │   │
│  │  - Frontend-Interaktion         │   │
│  └─────────────────────────────────┘   │
└─────────────────────────────────────────┘

Hauptkomponenten

KomponenteBeschreibung
Hauptprozess (Main Process)Verwaltet die App und erstellt Fenster
Renderer-Prozess (Renderer Process)Rendert die Web-Seiten in den Fenstern
IPC (Inter-Process Communication)Kommunikation zwischen den Prozessen

3.2 Hauptprozess (Main Process)

Aufgaben und Verantwortlichkeiten

Der Hauptprozess ist das Herzstück der Electron-App.

Hauptaufgaben

  1. App-Lebenszyklus verwalten

    • App starten, beenden, in den Hintergrund
  2. Fenster erstellen und verwalten

    • BrowserWindow instanziieren
    • Fenstereigenschaften festlegen
  3. Native APIs aufrufen

    • Menüs, Tray-Icons, Dialoge
  4. Node.js-Funktionen nutzen

    • Dateisystem, Netzwerk, Datenbanken

Beispiel: Hauptprozess (main.js)

javascript
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');

// Fenster erstellen
function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  });

  win.loadFile('index.html');
}

// App bereit
app.whenReady().then(() => {
  createWindow();
});

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

Wichtige Module im Hauptprozess

ModulFunktion
appApp-Lebenszyklus steuern
BrowserWindowFenster erstellen
ipcMainIPC-Nachrichten empfangen
MenuApp-Menüs erstellen
TrayTray-Icons erstellen
dialogSystem-Dialoge anzeigen

3.3 Renderer-Prozess (Renderer Process)

Aufgaben und Verantwortlichkeiten

Der Renderer-Prozess ist für die Anzeige der Benutzeroberfläche zuständig.

Hauptaufgaben

  1. UI rendern

    • HTML/CSS/JavaScript ausführen
    • Web-Seiten anzeigen
  2. Frontend-Interaktion verarbeiten

    • Button-Klicks, Formulareingaben
    • DOM-Manipulation
  3. Mit Hauptprozess kommunizieren

    • Über IPC Nachrichten senden
    • Daten anfordern

Beispiel: Renderer-Prozess (renderer.js)

javascript
// renderer.js
console.log('Renderer-Prozess gestartet');

// DOM-Elemente
const button = document.getElementById('myButton');
const output = document.getElementById('output');

// Button-Klick
button.addEventListener('click', () => {
  output.textContent = 'Button geklickt!';
  
  // Nachricht an Hauptprozess senden
  window.api.sendMessage('Hallo vom Renderer!');
});

// Nachricht vom Hauptprozess empfangen
window.api.onMessage((event, data) => {
  console.log('Vom Hauptprozess:', data);
});

Wichtige Punkte zum Renderer-Prozess

☑ Jedes Fenster hat einen eigenen Renderer-Prozess
☑ Mehrere Fenster = Mehrere Renderer-Prozesse
☑ Jeder Renderer-Prozess ist isoliert (Sicherheit)
☑ Standardmäßig kein direkter Node.js-Zugriff (contextIsolation)

3.4 Unterschiede zwischen Haupt- und Renderer-Prozess

Vergleichstabelle

AspektHauptprozessRenderer-Prozess
LaufzeitumgebungNode.jsChromium (Browser)
Zugriff auf Node.jsJa (vollständig)Nein (bei contextIsolation)
Fenster erstellenJaNein
Native APIsJaNein (nur über IPC)
App-LebenszyklusJaNein
UI-RenderingNeinJa
IPC-RolleEmpfänger/SenderSender/Empfänger

Berechtigungsunterschiede

Hauptprozess:
✓ Vollständiger Zugriff auf Node.js
✓ Native Betriebssystem-APIs
✓ Fensterverwaltung
✓ App-Lebenszyklus

Renderer-Prozess:
✓ Web-APIs (DOM, fetch, localStorage)
✗ Kein direkter Node.js-Zugriff (sicherheitshalber)
✗ Keine nativen APIs (nur über IPC)

Kommunikationsweise

Renderer-Prozess → IPC → Hauptprozess

Hauptprozess → IPC → Renderer-Prozess

3.5 Prozesskommunikation (IPC) Grundlagen

Was ist IPC?

IPC (Inter-Process Communication) ist der Mechanismus, mit dem Haupt- und Renderer-Prozesse Daten austauschen.

Grundlegende IPC-Konzepte

Renderer-Prozess                     Hauptprozess
      │                                    │
      │   ipcRenderer.send()              │
      │───────────────────────────────────>│
      │                                    │ ipcMain.on()
      │                                    │
      │   ipcRenderer.on()                │
      │<───────────────────────────────────│
      │                                    │ event.reply()

Kernmodule

ModulProzessFunktion
ipcMainHauptprozessNachrichten vom Renderer empfangen
ipcRendererRenderer-ProzessNachrichten an Hauptprozess senden

3.6 Praxisbeispiel: Einfache IPC-Kommunikation

Projektstruktur

ipc-beispiel/
├── main.js           # Hauptprozess
├── preload.js        # Preload-Skript (IPC-Brücke)
├── index.html        # UI
└── package.json

Schritt 1: preload.js erstellen (IPC-Brücke)

javascript
// preload.js - Sichere IPC-Brücke
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('api', {
  // Nachricht an Hauptprozess senden
  sendMessage: (message) => {
    ipcRenderer.send('message-from-renderer', message);
  },
  
  // Auf Nachrichten vom Hauptprozess hören
  onMessage: (callback) => {
    ipcRenderer.on('message-from-main', (event, data) => {
      callback(event, data);
    });
  }
});

Schritt 2: main.js konfigurieren

javascript
// main.js
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,  // Sicherheit: isoliert
      nodeIntegration: false   // Sicherheit: kein Node.js im Renderer
    }
  });

  win.loadFile('index.html');
}

// Nachricht vom Renderer empfangen
ipcMain.on('message-from-renderer', (event, message) => {
  console.log('Vom Renderer:', message);
  
  // Antwort an Renderer senden
  event.reply('message-from-main', `Antwort: ${message.toUpperCase()}`);
});

app.whenReady().then(createWindow);

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

Schritt 3: index.html erstellen

html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>IPC Beispiel</title>
  <style>
    body { font-family: Arial; padding: 20px; }
    button { padding: 10px 20px; margin: 10px; }
    #output { margin-top: 20px; padding: 10px; background: #f0f0f0; }
  </style>
</head>
<body>
  <h1>IPC Kommunikation Beispiel</h1>
  
  <input type="text" id="messageInput" placeholder="Nachricht eingeben">
  <button id="sendButton">Senden</button>
  
  <div id="output"></div>

  <script>
    const input = document.getElementById('messageInput');
    const button = document.getElementById('sendButton');
    const output = document.getElementById('output');

    // Button-Klick: Nachricht senden
    button.addEventListener('click', () => {
      const message = input.value;
      window.api.sendMessage(message);
      output.innerHTML += `<p>Gesendet: ${message}</p>`;
      input.value = '';
    });

    // Auf Antwort vom Hauptprozess hören
    window.api.onMessage((event, data) => {
      output.innerHTML += `<p><strong>Antwort:</strong> ${data}</p>`;
    });
  </script>
</body>
</html>

Schritt 4: Anwendung testen

bash
npm start

Erwartetes Ergebnis:

1. Eingabefeld und Button werden angezeigt
2. Nachricht eingeben und "Senden" klicken
3. Konsole im Hauptprozess zeigt: "Vom Renderer: [Nachricht]"
4. UI zeigt die Antwort vom Hauptprozess

3.7 Häufige Anfängerfehler

Fehler 1: Haupt- und Renderer-Prozess verwechseln

Symptom: Funktionen funktionieren nicht wie erwartet.

Lösung:

☑ Prüfen: Ist der Code im Haupt- oder Renderer-Prozess?
☑ Hauptprozess: Node.js-Module verwenden
☑ Renderer-Prozess: Web-APIs verwenden

Fehler 2: IPC-Kommunikation schlägt fehl

Ursachen und Lösungen:

ProblemUrsacheLösung
Nachricht kommt nicht anFalscher KanalnameKanalnamen exakt gleich schreiben
ipcRenderer nicht gefundennodeIntegration: falsePreload-Skript verwenden
SicherheitswarnungcontextIsolation: falsecontextIsolation: true + Preload

Fehler 3: Preload-Skript nicht korrekt konfiguriert

Richtige Konfiguration in main.js:

javascript
const win = new BrowserWindow({
  webPreferences: {
    preload: path.join(__dirname, 'preload.js'),  // WICHTIG!
    contextIsolation: true,
    nodeIntegration: false
  }
});

Fehler 4: IPC-Listener mehrfach registriert

Fehler:

javascript
// FALSCH: Jedes Mal wenn die Komponente gerendert wird
ipcRenderer.on('channel', callback);

Richtig:

javascript
// RICHTIG: Einmal registrieren oder vorher entfernen
ipcRenderer.removeAllListeners('channel');
ipcRenderer.on('channel', callback);

Zusammenfassung

In diesem Kapitel haben Sie gelernt:

  • Die Electron-Architektur (Haupt- und Renderer-Prozess)
  • Aufgaben und Verantwortlichkeiten beider Prozesse
  • Unterschiede in Berechtigungen und Laufzeitumgebung
  • Grundlagen der IPC-Kommunikation
  • Ein praktisches IPC-Beispiel zu implementieren
  • Häufige Anfängerfehler zu vermeiden

Im nächsten Kapitel werden wir die Electron-Kern dateien im Detail analysieren.

Frei für alle Anfänger