Tag: electron, desktop, javascript, nodejs, chromium, ipc
Livello: intermedio
TL;DR: Framework for building cross-platform native desktop applications using web technologies (HTML, CSS, JavaScript) by combining Chromium and Node.js environments.
The Main Process runs the package.json main script, creates application windows, and manages native system events.
The Renderer Process runs the user interface (web page) for a single browser window.
Inter-Process Communication (IPC) is strictly required to pass messages and data between the Main and Renderer processes.
Context Isolation is a core security feature ensuring scripts running in the renderer cannot directly access Node.js APIs or the preload context.
Preload scripts act as a secure bridge, exposing only specific, permitted Main process functionalities to the Renderer via contextBridge.
Production security mandates disabling nodeIntegration and enabling contextIsolation whenever rendering remote or untrusted content.
Packaging and distribution are typically handled via tools like Electron Builder or Electron Forge.
Q: How do the Main and Renderer processes communicate securely?R: I use the ipcMain and ipcRenderer modules. I always expose specific, constrained channels through a preload script using contextBridge rather than allowing direct IPC access.
Q: What is the difference between nodeIntegration and contextIsolation?R: nodeIntegration allows the renderer to use Node.js modules directly, which is dangerous. contextIsolation separates the V8 JavaScript contexts of the renderer and preload scripts to prevent privilege escalation and prototype pollution.
Q: How do you prevent the UI from freezing during heavy computation?R: I offload heavy CPU-bound tasks to Node.js worker threads or utility processes managed by the Main process, ensuring the Renderer and Main event loops remain unblocked.
Enabling nodeIntegration: true on browser windows that load external or untrusted URLs.
Executing heavy synchronous operations in the Main process, which completely freezes the application's GUI.
Forgetting to handle the window-all-closed event conditionally for macOS (process.platform !== 'darwin'), breaking standard Mac application behavior.
Leaking memory by failing to unsubscribe from IPC event listeners when a renderer window is destroyed.
// main.ts
import { app, BrowserWindow, ipcMain } from 'electron';
import * as path from 'path';
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false
}
});
win.loadFile('index.html');
}
app.whenReady().then(() => {
ipcMain.handle('ping', () => 'pong');
createWindow();
});
// preload.ts
import { contextBridge, ipcRenderer } from 'electron';
contextBridge.exposeInMainWorld('electronAPI', {
ping: () => ipcRenderer.invoke('ping')
});
// renderer.ts (usage)
// const response = await window.electronAPI.ping();