00
:
00
:
00
:
00
Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

Main Process e Renderer Process

L’architettura di Electron si basa su una separazione netta tra due tipi di processi: il Main Process e i Renderer Process. Comprendere questa distinzione è fondamentale per sviluppare applicazioni Electron sicure e performanti.

Il Main Process

Il Main Process è il processo principale dell’applicazione. Esiste un solo Main Process per applicazione ed è il primo ad essere eseguito.

Responsabilità del Main Process

  • Gestire il ciclo di vita dell’applicazione (avvio, chiusura, eventi di sistema)
  • Creare e gestire le finestre (BrowserWindow)
  • Accedere alle API native del sistema operativo
  • Gestire i menu, i dialog e il tray
  • Comunicare con i Renderer Process tramite IPC

API Disponibili

Il Main Process ha accesso a:

  • Tutte le API di Node.js (fs, path, child_process, etc.)
  • Le API di Electron dedicate al main: app, BrowserWindow, Menu, Tray, dialog, globalShortcut, ipcMain, etc.
// main.js - Esempio di Main Process completo
const { app, BrowserWindow, Menu, dialog } = require('electron');
const path = require('node:path');
const fs = require('node:fs');

let mainWindow;

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false,    // Sicurezza: disabilitato
      contextIsolation: true,     // Sicurezza: abilitato
    },
  });

  mainWindow.loadFile('index.html');

  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

app.whenReady().then(createWindow);

Il Renderer Process

Ogni finestra (BrowserWindow) esegue il proprio Renderer Process. Puoi pensare ad esso come un tab del browser — renderizza HTML, CSS e JavaScript.

Responsabilità del Renderer Process

  • Renderizzare l’interfaccia utente (HTML + CSS)
  • Gestire la logica dell’UI (interazioni utente, animazioni)
  • Comunicare con il Main Process tramite IPC (attraverso il preload)

API Disponibili

Il Renderer Process ha accesso a:

  • Tutte le Web API del browser (DOM, fetch, localStorage, Canvas, etc.)
  • Le API esposte tramite il preload script via contextBridge
  • Non ha accesso diretto a Node.js (per sicurezza)
// renderer.js - Esempio di Renderer Process
document.getElementById('open-btn').addEventListener('click', async () => {
  // Usa l'API esposta dal preload per comunicare col Main Process
  const filePath = await window.electronAPI.openFile();
  if (filePath) {
    document.getElementById('file-path').textContent = filePath;
  }
});

Differenze Principali

Caratteristica Main Process Renderer Process
Quanti Uno solo Uno per finestra
Accesso Node.js Completo No (via preload)
Accesso DOM No Completo
API Electron app, BrowserWindow, Menu, etc. Solo via preload
Web API No Complete
Ruolo Backend / Sistema Frontend / UI

Ciclo di Vita dell’App

Il Main Process gestisce l’intero ciclo di vita dell’applicazione attraverso gli eventi dell’oggetto app:

const { app } = require('electron');

// L'app è pronta per creare finestre
app.whenReady().then(() => {
  console.log('App pronta!');
  createWindow();
});

// Tutte le finestre sono state chiuse
app.on('window-all-closed', () => {
  // Su macOS le app restano attive fino a Cmd+Q
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

// (macOS) L'app è stata attivata dal dock
app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});

// L'app sta per chiudersi
app.on('before-quit', () => {
  console.log('Salvataggio in corso...');
});

// Impedire la chiusura della finestra (es. per chiedere conferma)
app.on('will-quit', (event) => {
  // event.preventDefault(); // Impedisce la chiusura
});

Comunicazione tra Processi

Main e Renderer Process sono isolati tra loro. Non possono accedere direttamente alle variabili o funzioni dell’altro. La comunicazione avviene tramite IPC (Inter-Process Communication):

┌──────────────┐         IPC          ┌──────────────┐
│ Main Process │ ◄──────────────────► │  Renderer    │
│              │   ipcMain/ipcRenderer│  Process     │
│  - Node.js   │         +            │  - DOM       │
│  - API OS    │   contextBridge      │  - Web API   │
│  - Finestre  │                      │  - UI Logic  │
└──────────────┘                      └──────────────┘

La comunicazione IPC è trattata in dettaglio nella sezione dedicata.

Multiple Renderer Process

Ogni finestra dell’app ha il proprio Renderer Process indipendente:

function createMainWindow() {
  const mainWindow = new BrowserWindow({ width: 1200, height: 800 });
  mainWindow.loadFile('index.html');
  // Renderer Process #1
}

function createSettingsWindow() {
  const settingsWindow = new BrowserWindow({ width: 600, height: 400 });
  settingsWindow.loadFile('settings.html');
  // Renderer Process #2
}

I Renderer Process non possono comunicare direttamente tra loro. Devono passare attraverso il Main Process come intermediario.

Best Practice

  1. Non abilitare nodeIntegration nel Renderer Process — è un rischio per la sicurezza
  2. Sempre abilitare contextIsolation — isola il preload dal contenuto web
  3. Usare il preload script per esporre solo le API necessarie al renderer
  4. Tenere la logica pesante nel Main Process — il renderer deve concentrarsi sull’UI
  5. Non bloccare il Main Process — operazioni lunghe vanno eseguite in modo asincrono o in worker thread