Skip to content

Kapitel 4: Electron-Kern dateien analysieren

In diesem Kapitel analysieren wir die wichtigsten Dateien einer Electron-App im Detail.

4.1 package.json (Electron-Projektkonfiguration)

Die package.json ist das Herzstück der Projektkonfiguration.

Grundlegende Struktur

json
{
  "name": "meine-electron-app",
  "version": "1.0.0",
  "description": "Meine erste Electron-App",
  "main": "main.js",
  "scripts": {
    "start": "electron .",
    "build": "electron-builder"
  },
  "keywords": ["electron", "desktop"],
  "author": "Ihr Name",
  "license": "MIT",
  "devDependencies": {
    "electron": "^31.0.0",
    "electron-builder": "^24.0.0"
  },
  "dependencies": {
    "electron-store": "^8.1.0"
  }
}

Wichtige Felder im Detail

main-Feld: Hauptprozess-Einstiegsdatei

json
{
  "main": "main.js"
}
AspektErklärung
FunktionLegt fest, welche Datei als Hauptprozess ausgeführt wird
Standardmain.js (falls nicht angegeben)
WichtigMuss existieren und korrekten Pfad haben

scripts-Feld: Start- und Build-Skripte

json
{
  "scripts": {
    "start": "electron .",
    "dev": "electron . --dev",
    "build:win": "electron-builder --win",
    "build:mac": "electron-builder --mac",
    "build:linux": "electron-builder --linux"
  }
}
SkriptBefehlFunktion
startnpm startApp im Entwicklungsmodus starten
devnpm run devApp mit DevTools starten
build:winnpm run build:winWindows-Installer erstellen
build:macnpm run build:macmacOS-Installer erstellen

devDependencies vs. dependencies

json
{
  "devDependencies": {
    "electron": "^31.0.0",
    "electron-builder": "^24.0.0"
  },
  "dependencies": {
    "electron-store": "^8.1.0",
    "axios": "^1.6.0"
  }
}
TypErklärungBeispiel
devDependenciesNur für Entwicklungelectron, electron-builder
dependenciesZur Laufzeit benötigtelectron-store, axios

Electron-spezifische Konfiguration

json
{
  "name": "meine-app",
  "version": "1.0.0",
  "main": "main.js",
  "build": {
    "appId": "com.beispiel.meineapp",
    "productName": "Meine App",
    "directories": {
      "output": "dist"
    },
    "win": {
      "target": "nsis",
      "icon": "assets/icon.ico"
    },
    "mac": {
      "target": "dmg",
      "icon": "assets/icon.icns"
    }
  }
}

4.2 Hauptprozess-Einstiegsdatei (main.js)

Die main.js ist die wichtigste Datei im Hauptprozess.

Grundgerüst

javascript
// main.js
const { app, BrowserWindow } = 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'),
      contextIsolation: true,
      nodeIntegration: false
    }
  });

  // HTML-Datei laden
  win.loadFile('index.html');
  
  // DevTools öffnen (nur in Entwicklung)
  // win.webContents.openDevTools();
}

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

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

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

app-Modul: App-Lebenszyklus steuern

Wichtige App-Ereignisse

javascript
// App startet
app.on('ready', () => {
  console.log('App bereit');
});

// App wird aktiviert (macOS)
app.on('activate', () => {
  console.log('App aktiviert');
});

// App wird beendet
app.on('before-quit', (event) => {
  console.log('App wird beendet');
});

// Alle Fenster geschlossen
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});
EreignisBeschreibung
readyApp ist bereit (veraltet, nutze whenReady())
whenReady()Promise, wenn App bereit ist
activateApp wird aktiviert (macOS Dock-Klick)
before-quitBevor App beendet wird
will-quitApp wird beendet
window-all-closedAlle Fenster geschlossen

BrowserWindow: Anwendungsfenster erstellen

Grundlegende Konfiguration

javascript
const win = new BrowserWindow({
  width: 1200,           // Breite
  height: 800,            // Höhe
  x: 100,                // X-Position
  y: 100,                // Y-Position
  title: 'Meine App',    // Fenstertitel
  icon: 'icon.png',       // Fenstericon
  show: false,            // Fenster erst anzeigen, wenn bereit
  frame: true,            // Fensterrahmen (false = frameless)
  resizable: true,        // Größe änderbar
  minimizable: true,      // Minimierbar
  maximizable: true,      // Maximierbar
  closable: true,         // Schließbar
  alwaysOnTop: false,     // Immer im Vordergrund
  fullscreen: false,      // Vollbildmodus
  transparent: false,     // Transparenter Hintergrund
  backgroundColor: '#fff', // Hintergrundfarbe
  webPreferences: {
    preload: path.join(__dirname, 'preload.js'),
    contextIsolation: true,
    nodeIntegration: false,
    webSecurity: true
  }
});

Fenster laden: loadFile und loadURL

javascript
// Lokale HTML-Datei laden
win.loadFile('index.html');

// Absolute Pfad
win.loadFile(path.join(__dirname, 'renderer', 'index.html'));

// Remote-URL laden
win.loadURL('https://example.com');

// Mit zusätzlichen Optionen
win.loadURL('https://example.com', {
  extraHeaders: 'Authorization: Bearer token'
});
MethodeVerwendungBeispiel
loadFile()Lokale HTML-Datei ladenwin.loadFile('index.html')
loadURL()Remote-URL oder lokaler Serverwin.loadURL('http://localhost:3000')

4.3 Renderer-Prozess-Seiten (index.html / renderer.js)

HTML-Seite (index.html)

html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="Content-Security-Policy" 
        content="default-src 'self' 'unsafe-inline';">
  <title>Meine Electron-App</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div id="app">
    <h1>Willkommen in meiner App!</h1>
    <button id="myButton">Klick mich</button>
    <div id="output"></div>
  </div>

  <script src="renderer.js"></script>
</body>
</html>

Renderer-Skript (renderer.js)

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

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

// Event-Listener
button.addEventListener('click', () => {
  output.textContent = 'Button wurde geklickt!';
  
  // Nachricht an Hauptprozess senden (über Preload)
  window.api.sendMessage('Button geklickt');
});

// Nachricht vom Hauptprozess empfangen
window.api.onMessage((event, data) => {
  console.log('Vom Hauptprozess:', data);
  output.textContent += `\nAntwort: ${data}`;
});

Content Security Policy (CSP)

html
<!-- WICHTIG für Sicherheit -->
<meta http-equiv="Content-Security-Policy" 
      content="
        default-src 'self';
        script-src 'self';
        style-src 'self' 'unsafe-inline';
        img-src 'self' data:;
        connect-src 'self';
      ">

4.4 Praxisbeispiel: Kernkonfiguration ändern

Ziel: Anwendungsfenster und Startverhalten anpassen

Schritt 1: Benutzerdefinierte Fenstergröße und Position

javascript
// main.js
function createWindow() {
  const win = new BrowserWindow({
    width: 1400,
    height: 900,
    minWidth: 800,
    minHeight: 600,
    x: 50,
    y: 50,
    title: 'Meine Angepasste App',
    icon: path.join(__dirname, 'assets', 'icon.png'),
    show: false,  // Erst anzeigen, wenn bereit
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  });

  // Fenster erst anzeigen, wenn Inhalt geladen ist
  win.once('ready-to-show', () => {
    win.show();
  });

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

Schritt 2: Startverhalten anpassen

javascript
// Splash-Screen anzeigen
app.whenReady().then(() => {
  // Splash-Screen
  const splash = new BrowserWindow({
    width: 400,
    height: 300,
    frame: false,
    transparent: true,
    alwaysOnTop: true,
    center: true
  });
  
  splash.loadFile('splash.html');
  
  // Hauptfenster erstellen
  const mainWin = new BrowserWindow({
    width: 1200,
    height: 800,
    show: false
  });
  
  mainWin.loadFile('index.html');
  
  // Nach 2 Sekunden Splash schließen und Hauptfenster zeigen
  setTimeout(() => {
    splash.destroy();
    mainWin.show();
  }, 2000);
});

Schritt 3: Zweites Fenster öffnen

javascript
// In main.js
let secondWin;

function createSecondWindow() {
  secondWin = new BrowserWindow({
    width: 600,
    height: 400,
    parent: mainWin,  // Übergeordnetes Fenster
    modal: true,       // Modales Fenster
    show: false
  });

  secondWin.loadFile('second.html');
  
  secondWin.once('ready-to-show', () => {
    secondWin.show();
  });
}

// IPC-Handler für zweites Fenster
ipcMain.on('open-second-window', () => {
  createSecondWindow();
});

Zusammenfassung

In diesem Kapitel haben Sie gelernt:

  • Die package.json für Electron zu konfigurieren
  • Die main.js (Hauptprozess) im Detail zu verstehen
  • app- und BrowserWindow-Module zu nutzen
  • Renderer-Prozess-Seiten zu erstellen
  • Konfigurationen anzupassen

Im nächsten Kapitel werden wir Fensteroperationen im Detail behandeln.

Frei für alle Anfänger