Veröffentlicht · wird verbessert
Electron-Anleitung · 3/6
Dieses Kapitel ist vorerst nur auf Englisch verfügbar.
Using Electron well means understanding its process model, how processes talk to each other over IPC, and the security model built on top of both. This chapter covers BrowserWindow, ipcMain and ipcRenderer, contextBridge, context isolation, and the security checklist.
Electron inherits Chromium's multi-process architecture.
app), windows (BrowserWindow), menus, the tray, dialogs, and other native features.webContents), each running a web page. By default they have no Node.js access.utilityProcess.fork(). Use them to move heavy computation or crash-prone work out of the main process.If the main process is blocked by a long task, every window appears frozen. Move heavy work to asynchronous APIs or a utility process.
// main.js
const { utilityProcess } = require('electron')
const path = require('node:path')
const child = utilityProcess.fork(path.join(__dirname, 'worker.js'))
child.on('message', (result) => console.log('result:', result))
child.postMessage({ numbers: [1, 2, 3] })
// worker.js
process.parentPort.on('message', (event) => {
const sum = event.data.numbers.reduce((a, b) => a + b, 0)
process.parentPort.postMessage(sum)
})A BrowserWindow creates one native window and the renderer inside it. Alongside window options such as size, frame, and minimum size, webPreferences sets the renderer's security options.
const win = new BrowserWindow({
width: 1000,
height: 700,
minWidth: 600,
show: false, // show once content is ready to avoid a flash
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true, // default
nodeIntegration: false, // default
sandbox: true, // default
},
})
win.once('ready-to-show', () => win.show())
win.loadFile('index.html')contextIsolation, nodeIntegration: false, and sandbox are already the defaults in current Electron. Spelling them out documents the intent and makes an accidental change easy to spot in review.
Renderers cannot reach the operating system directly, so they ask the main process over IPC. The most common pattern is request and response: register a handler in the main process with ipcMain.handle, call it from the renderer side (the preload) with , and receive the result as a Promise.
ipcRenderer.invoke// main.js
const { ipcMain, dialog } = require('electron')
ipcMain.handle('dialog:openFile', async (event) => {
const { canceled, filePaths } = await dialog.showOpenDialog({ properties: ['openFile'] })
return canceled ? null : filePaths[0]
})// preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('api', {
openFile: () => ipcRenderer.invoke('dialog:openFile'),
setTitle: (title) => ipcRenderer.send('set-title', title),
onUpdateCounter: (callback) => {
ipcRenderer.on('update-counter', (_event, value) => callback(value))
},
})Fire-and-forget messages use ipcRenderer.send with ipcMain.on. When the main process needs to notify a renderer first, it calls win.webContents.send, and the preload listens with ipcRenderer.on and forwards the value to a callback.
// main.js
ipcMain.on('set-title', (event, title) => {
const win = BrowserWindow.fromWebContents(event.sender)
win.setTitle(title)
})
win.webContents.send('update-counter', 1)
// renderer.js
document.getElementById('open').addEventListener('click', async () => {
const filePath = await window.api.openFile()
if (filePath) document.getElementById('file').textContent = filePath
})
window.api.onUpdateCounter((value) => console.log('counter:', value))With context isolation enabled, the preload script and the web page run in separate JavaScript worlds. Scripts on the page cannot tamper with the preload's variables or with Electron APIs. The only passage between the two worlds is contextBridge.exposeInMainWorld; only the functions and values passed through it are visible to the page.
Exposing the entire ipcRenderer object would let the page send messages on any channel and defeat the isolation. Expose narrow, purpose-built functions as in the example above, and do not hand the raw event object to page callbacks.
The heart of Electron's official security checklist:
nodeIntegration in renderers.contextIsolation or sandbox.event.senderFrame) and the arguments of every IPC message.shell.openExternal.win.webContents.setWindowOpenHandler(({ url }) => {
if (url.startsWith('https://example.com/')) shell.openExternal(url)
return { action: 'deny' }
})
win.webContents.on('will-navigate', (event, url) => {
if (!url.startsWith('file://')) event.preventDefault()
})ipcMain.handle with ipcRenderer.invoke for request and response, send with on for one-way messages, and webContents.send from main to renderer.contextBridge.
0 Kommentare
Anmelden · Melde dich an, um einen Kommentar zu schreiben.
Schreib den ersten Kommentar.