ยท hands on
Anatomy of an Electron 4 application
In Electron 4 applications, there are two main processes: the main process and the renderer process. The main process is responsible for displaying the GUI, managing BrowserWindow instances and registering global shortcuts.
Overview of main concepts in Electron 4 applications.
Contents
main process
Every Electron app has one (and just one!) main process. The main process is used to display a GUI and started from the main script defined package.json
.
Concerns
- Entry point for Electron applications
- Creates and manages BrowserWindow instances
- Registers global shortcuts
- Creates native menus
- Shows native GUI
- Responds to auto-update events
renderer process
Each web page in Electron runs in a separate renderer process. If not limited, web pages running in a renderer process have to power to access Node.js modules.
Concerns
- Takes care of showing your HTML & JS in the Chromium browser
- Runs UI in webContents instances
- Access information about audio and video devices using desktopCapturer
- Can access main process modules via remote module
Characteristics
process.type
is"renderer"
Example
const { desktopCapturer, ipcRenderer, webFrame } = require('electron');
const { app } = require('electron').remote;
webFrame.setZoomFactor(1.0);
webFrame.setVisualZoomLevelLimits(1, 1);
console.log('App configuration directory', app.getPath('userData'));
Inter-process communication (IPC)
Using inter-process communication a renderer process can exchange messages with a main process:
import {ipcRenderer} from 'electron';
const updateBtn = document.getElementById('updateBtn')
updateBtn.addEventListener('click', () => {
ipcRenderer.send('my-app-event', document.getElementById('notifyVal').value);
});
import {BrowserWindow, ipcMain, IpcMessageEvent} from 'electron';
const main = new BrowserWindow();
ipcMain.on('my-app-event', (event: IpcMessageEvent, price: number) => {
main.webContents.send('target-price', price);
});
Note: ipcRenderer
does not send messages to itself, it sends them to ipcMain
. If you want to access the messages within a renderer process, you need to check ipcMain
using electron.remote
:
import {remote} from 'electron';
// ...
remote.ipcMain.on('my-app-event', (event, price) => {
console.log(`Received "${price}" in renderer process.`);
});
Webview Preload Script
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<script>
require('./renderer.js');
</script>
<body>
<webview
preload="./preload.js"
src="https://benny.work"
></webview>
</body>
</html>
You can assign a preload script programmatically:
import fileUrl = require('file-url');
const main = new BrowserWindow();
const contents = main.webContents;
contents.on('will-attach-webview', (event, webPreferences, params) => {
webPreferences.preloadURL = fileUrl('./preload.js');
});
const {ipcRenderer} = require('electron');
window.addEventListener('DOMContentLoaded', () => {
// From guest (webview content) to host (main process)
window.addEventListener(z.event.WebApp.LIFECYCLE.RESTART, (event) => {
ipcRenderer.send(EVENT_TYPE.WRAPPER.RELAUNCH);
});
// From host (main process) to guest (webview content)
ipcRenderer.on(EVENT_TYPE.WRAPPER.RELAUNCHED, () => {
window.dispatchEvent(new CustomEvent(EVENT_TYPE.ACTION.CREATE_ACCOUNT));
});
});
import {BrowserWindow} from 'electron';
const main = new BrowserWindow();
main.loadFile('index.html');
ipcMain.on(
EVENT_TYPE.WRAPPER.RELAUNCH,
async (event: IpcMessageEvent) => {
console.log('Do some work and send a reply...');
main.webContents.send(EVENT_TYPE.WRAPPER.RELAUNCHED);
}
);