In diesem Quick-Start-Guide findest du alle Informationen, um sofort mit der Entwicklung deiner App in Electron zu starten.


Der Guide besteht aus mehreren Teilen. Hier in Teil 2 „Electron Quick-Start: Entwicklung“ geht es um die Entwicklung der App, also um das Programmieren an sich. Die Links unten führen dich zu den anderen Kapiteln des Guides.

Eine Zusammenfassung (Nur einzelne Schritte, keine Erklärungen & Vorlagen für alle Dateien) aller drei Kapitel ist hier verfügbar:


Entwicklung – Inhalt

Was soll unsere App tun?

Die hier gezeigte App ist ein sehr einfaches Grundgerüst als Beispiel dafür, wie eine Electron App funktioniert. Natürlich kann das nur ein Anfang sein.

Ein Feature, das man eigentlich immer braucht, wenn es darum geht in Electron eine App zu schreiben, ist die Inter-Prozess-Kommunikation (IPC), die es ermöglicht, Daten zwischen verschiedenen Prozessen auszutauschen. Daher werden wir hier die IPC zwischen Main, Preload und Index ansehen.

Weitere Features von Node.js, wie zum Beispiel das Dateisystem (FS) lassen wir hier bewusst erst einmal aus – um den hier verwendeten Code simpel zu halten.

Main.js erstellen

Im vorherigen Teil des Tutorials haben wir in unserer package-Datei („package.json“) festgelegt, dass der „Entry-Point“ unserer App eine Datei namens „main.js“ sein soll. Startet man also unsere App, dann wird zuerst das Script „main.js“ ausgeführt. Genau dieses Script erstellen wir jetzt.

1. Main.js erstellen

Erstelle eine Datei mit dem Namen „main.js“ im Projektverzeichnis.

Nutze dazu entweder das PS Kommando „New-Item main.js“ im VS-Code Terminal, oder nutze den Dateiexplorer in VS-Code. (Klicke auf oder mache einen Rechtklick in den Explorer und dann auf „Neue Datei“).

Lade main.js durch einen Doppelklick in den Editor.

2. Benötigte Module laden

Jetzt kümmern wir uns darum, dass main.js auch tut, was es soll: main.js läuft nach dem Start der App im Hintergrund, öffnet Fenster, verwaltet Dateien, usw.

Kopiere folgende Zeilen in die Datei:

// Module Laden
const { app, BrowserWindow } = require('electron');
const path = require("path");

// Fenster definieren
let window;Code-Sprache: JavaScript (javascript)

Mittels „require“ werden verschiedene JS-Module geladen, und deren Funktionen dadurch in unserem Script verfügbar. In unserem Fall sind das die Module „app“, „BrowserWindow“ und „path“.

Diese Module kommen nativ mit Electron bzw. Node.js, und müssen deswegen vorher nicht heruntergeladen werden. Wie man neue Module via NPM bezieht, schauen wir uns später noch einmal an.

„window“ ist eine Variable, die später das Browserfenster definiert, das wir dem User anzeigen möchten.

3. Fenster definieren

Kopiere folgende Zeilen in die Datei:

// Fenster definieren
const createWindow = () => {
    window = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            nodeIntegration: false,
            contextIsolation: true,
            enableRemoteModule: false,
            preload: path.join(__dirname, "preload.js")
        },
    }),
    window.loadFile('index.html')
}Code-Sprache: JavaScript (javascript)

Hier definieren wir das neue Fenster: Höhe, Breite, und der Inhalt der geladen werden soll, werden festgelegt. In unserem Fall wird das Fenster 800 * 600 Pixel groß sein, und geladen wird index.html als Inhalt.

In den webPreferences sind einige sicherheitsrelevante Einstellungen festgelegt, die vor allem auch dann wichtig sind, wenn du statt einer lokalen Datei, wie index.html (die wir noch erstellen werden) eine Website aus dem Internet laden möchtest.

Damit aber doch einige Funktionen, wie z.B. IPC im für den User sichtbaren Fenster genutzt werden können, benutzen wir ein preload script („preload.js“), das wir auch noch erstellen werden.

4. Fenster anzeigen

Electron hat eine eingebaute Funktion, um zu bestimmen, wann der Hintergrundprozess bereit ist, den Render-Prozess anzuzeigen: whenReady(). Der Render-Prozess stellt das eben definierte Fenster über den Chromium-Browser auf dem Gerät der Nutzer:innen dar.

Kopiere folgende Zeilen in die Datei:

// Render-Prozess starten
app.whenReady().then(() => {  
    createWindow()
})Code-Sprache: JavaScript (javascript)

Jetzt wird die in Schritt 3 definierte Funktion aufgerufen, und beim Ausführen der App wird das Fenster nun durch den Render-Prozess angezeigt.

5. App beenden, wenn Fenster geschlossen wird

Kopiere folgende Zeilen in die Datei:

// Ausführung beenden, wenn Render-Prozess beendet
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})Code-Sprache: PHP (php)

Eine Erklärung, warum dieser Ausdruck nötig ist, findet sich im Exkurs unten. Weiter geht es dann mit dem Definieren eines Menüs für das GUI-Fenster.

Kleiner Exkurs: Prozessstruktur von Electron

Wie bereits kurz erwähnt, unterscheidet man den Hintergrund (oder „Main“)-Prozess und den Render-Prozess. Für unsere Zwecke reicht es, zu wissen, dass diese unabhängig von einander ausgeführt werden. Beendet man den Render-Prozess, bedeutet das nicht, dass auch der Main-Prozess (der main.js ausführt) beendet wird. Damit die App also nicht teilweise „heimlich“ im Hintergrund weiterläuft, koppeln wir das Schließen des Fensters (aus Schritt 3 & 4) an das Beenden aller Prozesse.

Bevor wir die App im dritten Teil dieses Tutorials als Programm (.exe) exportieren, werden wir die App immer über das Terminal via powershell starten.

Über das Terminal kann die Ausführung der App (inkl. des Main-Prozesses) auch wieder beendet werden, z.B. wenn sich der Render-Prozess aufhängt und die App nicht mehr ganz durch das Schließen des Fensters beendet werden kann! Gib dafür „strg + c“ ins Terminal ein und bestätige mit „y“ (gefolgt durch Enter). Alternativ können die Prozesse natürlich auch über den Windows-Taskmanager beendet werden.

Menü definieren

Ergänze die Module „Menu“ und „MenuItem“ ganz oben in main.js, so dass der Code aussieht wie folgt:

// Module Laden
const { app, BrowserWindow, Menu, MenuItem } = require('electron');Code-Sprache: JavaScript (javascript)

Füge den Code unten in main.js, direkt unter „let win; – noch vor „const createWindow = () => {ein.

// let win;...

// Menü definieren
const menu = new Menu()
menu.append(new MenuItem({
  label: 'Electron',
  submenu: [{
    label: 'Dev-Tools',
    accelerator: 'Ctrl+d',
    click: () => window.webContents.openDevTools()
  },{
    label: 'App schließen',
    accelerator: 'Ctrl+q',
    click: () => app.quit()
  }],
}))
menu.append(new MenuItem({
  label: 'Test',
  submenu: [{
    label: 'IPC',
    click: () => trigger_IPC()
  }],
}))
Menu.setApplicationMenu(menu)

// ... const createWindow = () => {Code-Sprache: JavaScript (javascript)

Durch diesen Code wird ein klickbares Menü im Electron-Render-Fenster geladen. Dieses wird zunächst zwei Buttons haben: „Electron“ & „Test“.
Klickt man auf Electron, kann man im Untermenü die Chrom-Entwicklertools öffnen. Das ist wichtig, weil dort die Konsole für den Render-Prozess ausgegeben wird. Was beim Klick auf „App schließen“ passiert, ist vermutlich selbsterklärend ;). Für beide Funktionen wird auch ein Tastatur-Shortcut registriert. Drückt man z.B. „Strg+d„, öffnen sich die Dev-Tools, ebenso wie bei einem Klick auf den Button.

Wichtig dabei: Die über das Menü definierten Tastatur-Shortcuts werden nur dann ausgeführt, wenn das Electron-Fenster gerade im Fokus („angeklickt“) ist. Über „globalShortcut.register()“ kann man auch einen systemweiten Shortcut einrichten, der eine Funktion auch dann ausführt, wenn das Fenster gerade nicht aktiv ist.

Die Funktion „trigger_IPC();“ werden wir im nächsten Schritt benutzen, um die Inter-Prozess-Kommunikation in Electron auszuprobieren.

IPC in Main.js

Grundsätzlich ist wichtig zu wissen, dass die IPC natürlich in zwei Richtungen funktioniert: Von Main zu Render-Prozess und umgekehrt.

Über den folgenden Code können wir Daten an preload.js (welches wir noch erstellen müssen!) senden, und machen diese so auch für den Render-Prozess verfügbar. Konkret heißt das, dass wir die Daten auch in Index.html verwenden können (auch Index.hmtl muss noch erstellt werden).

Ergänze das Modul „ipcMain“ ganz oben in main.js, so dass der Code aussieht wie folgt:

// Module Laden
const { app, BrowserWindow, Menu, MenuItem, ipcMain } = require('electron');Code-Sprache: JavaScript (javascript)

Füge folgende Funktion unten in main.js ein:

// IPC senden
function trigger_IPC () {
  window.webContents.send ('event1','Hi main.js hier!')
}

// IPC empfangen
ipcMain.on('answer1', (event, data) => {
  console.log(data)
})
ipcMain.on('answer2', (event, data) => {
  console.log(data)
})Code-Sprache: JavaScript (javascript)

Mehr zu ipcMain und webContents.

WICHTIG: IPC ist immer sicherheitsrelevant, vor allem, wenn du vor hast, eine Website aus dem Internet zu laden! Bitte informiere dich weitergehend und nutze dieses Tutorial nur als Inspiration!

Preload.js erstellen

Erstelle eine neue Datei namens preload.js im Projektverzeichnis und öffne sie im Editor. (Wie das geht ist hier beschrieben)

Kopiere den folgenden Code in in preload.js:

// Module laden
const {contextBridge, ipcRenderer} = require('electron')

// APIs im Render-Prozess verfügbar machen
contextBridge.exposeInMainWorld(
  'electron',
  {
    answer2: (data) => ipcRenderer.send('answer2', data),
  }
)

// IPC beantworten, wenn IPC von Main empfangen wird
ipcRenderer.on('event1', (event, data) => {
  console.log(data)
  ipcRenderer.send('answer1','Hi main.js, hier ist preload.js')
})Code-Sprache: JavaScript (javascript)

Weitere Erklärungen zu: preload.js, contextBride und ipcRenderer.

Index.html erstellen

Erstelle drei neue Dateien namens index.html, index.js und index.css im Projektverzeichnis und öffne sie im Editor.

Kopiere den folgenden Code in index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="index.css">
    <title>Tutorial-App</title>
  </head>

  <body>
    <h1>Hi, ich bin index.html!</h1>
    <a onclick="index_ipc()">Klick!</a>
  </body>

  <script src="index.js"></script>
</html>Code-Sprache: HTML, XML (xml)

Kopiere den folgenden Code in index.css:

body {
    background-color: darkblue;
    color: white;
}Code-Sprache: CSS (css)

Kopiere den folgenden Code in index.js:

function index_ipc () {
    window.electron.answer2('Hi zusammen, hier ist auch noch index.js!')
}Code-Sprache: JavaScript (javascript)

App starten

Führe das Kommando „npm start“ über die Konsole aus und warte bis sich das Fenster öffnet.

Darstellung der im Tutorial erarbeiteten App. Weiß auf blauem Grund ist zu lesen: "Hi, ich bin index.html! Klick!"
So sollte die von uns entwickelte App aussehen, wenn du sie startest.

Öffne die Dev-Tools über das Menü, oder indem du „Strg+d“ drückst.

Starte die Inter-Prozess-Kommunikation über das Menü (Test -> IPC).

Klicke auf „Klick!“ 😀

In der Konsole der Dev-Tools und in VS-Code kannst du die IPC verfolgen.


Der Guide besteht aus mehreren Teilen. Weiter geht es in Teil 3 mit dem Export der App in eine ausführbare Datei. Eine Zusammenfassung (Nur einzelne Schritte & Vorlagen für alle Dateien) ist ebenfalls verfügbar.