Architecture Electron
Vous pouvez considérer Electron comme :
Un conteneur d'application multi-processus avec un moteur de navigateur intégré (Chromium) et un environnement d'exécution Node.js,
Des applications de bureau qui combinent "pages web + capacités système" en coordonnant via une communication inter-processus (IPC).
Ses composants principaux sont :
| Rôle | Description | Analogie |
|---|---|---|
| Processus principal (main process) | Le cerveau d'Electron, contrôlant le cycle de vie de l'application, créant des fenêtres et appelant les API système | Gestionnaire de processus de l'OS |
| Processus de rendu | L'environnement de page web (HTML, CSS, JS) exécuté par chaque fenêtre | Onglet de navigateur |
| Script de préchargement | S'exécute avant le rendu, peut servir de pont pour les API du processus principal afin qu'elles soient utilisées par les pages web | Sécurité « couche intermédiaire » |
| IPC (communication inter-processus) | Canal de communication entre le processus principal et les processus de rendu | ligne téléphonique |
| Objet BrowserWindow | Le « conteneur de fenêtre » créé par le processus principal, qui charge les pages web à l'intérieur | Fenêtre de navigateur |
| Module d'application | Contrôle le cycle de vie de l'application (démarrage, fermeture) | Contrôle principal |
Processus principal
Le processus principal est le "cerveau" d'une application Electron ; chaque application Electron a exactement un processus principal. Il est responsable de :
- Créer et gérer les fenêtres de l'application(Processus de rendu)
- Gérer le cycle de vie de l'application(Démarrage, Fermeture, Basculement premier plan/arrière-plan)
- Interagir avec les API natives du système d'exploitation
- Gérer les composants au niveau du système tels que les menus et les boîtes de dialogue
Exemple
const { app, BrowserWindow } = require('electron');
function createWindow() {
// Créer la fenêtre de navigateur
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
// Charger l'index.html de l'application
mainWindow.loadFile('index.html');
}
// Appelé lorsque Electron termine l'initialisation
app.whenReady().then(createWindow);
Processus de rendu
Le processus de rendu est responsable de l'affichage de l'interface utilisateur ; chaque fenêtre Electron est un processus de rendu indépendant :
- S'exécute dans l'environnement du navigateur Chromium
- Utilisez HTML, CSS et JavaScript pour créer des interfaces
- Chaque fenêtre est un processus indépendant, et elles ne s'affectent pas mutuellement
- Communique avec le processus principal via IPC
Exemple
<!DOCTYPE html>
<html>
<head>
<title>Mon application Electron</title>
</head>
<body>
<h1>Bonjour Electron !</h1>
<button id="btn">Cliquez-moi</button>
<script>
// JavaScript dans le processus de rendu
document.getElementById('btn').addEventListener('click', () => {
alert('Le bouton a été cliqué !');
});
</script>
</body>
</html>
Scripts de préchargement
Le script de préchargement est le « pont » reliant le processus principal et le processus de rendu :
- S'exécute avant le chargement de la page web dans le processus de rendu
- A accès aux API Node.js et au DOM
- Exposer en toute sécurité des API au processus de rendu via contextBridge
Exemple
const { contextBridge, ipcRenderer } = require('electron');
// Exposer une API sécurisée au processus de rendu
contextBridge.exposeInMainWorld('electronAPI', {
showDialog: (message) => ipcRenderer.invoke('show-dialog', message)
});
Communication inter-processus (IPC)
Modèles de communication IPC
IPC(Inter-Process Communication)Est le cœur de communication d'Electron.
Comme le processus principal et le processus de rendu sont indépendants, les données doivent être transmises via IPC.

Direction de communication
| Type | Écoute du processus principal | Envoyé par le processus de rendu |
|---|---|---|
| Processus de rendu → Processus principal | ipcMain.on(channel, handler) |
ipcRenderer.send(channel, data) |
| Processus principal → Processus de rendu | event.sender.send(channel, data) |
ipcRenderer.on(channel, callback) |
Exemple de communication de base
Code du processus principal :
Exemple
// Écouter les messages du processus de rendu
ipcMain.handle('show-dialog', async (event, message) => {
const result = await dialog.showMessageBox({
type: 'info',
message: message,
buttons: ['OK', 'Annuler']
});
return result;
});
Code du processus de rendu :
Exemple
document.getElementById('btn').addEventListener('click', async () => {
const result = await window.electronAPI.showDialog('Bonjour, Electron !');
console.log('Utilisateur a cliqué :', result.response);
});
Avantages et fonctionnalités de l'architecture
Comparaison des avantages
| Fonctionnalités | Electron | Développement desktop traditionnel |
|---|---|---|
| Technologie de développement | Technologies web (HTML/CSS/JS) | Langages natifs (C++/C#/Java) |
| Prise en charge multiplateforme | Développer une fois, exécuter sur plusieurs plateformes | Nécessite un développement séparé pour chaque plateforme |
| Efficacité de développement | Élevé, tire parti de l’écosystème web existant | Plus faible, nécessite d’apprendre des technologies spécifiques à la plateforme |
| Performance | Relativement faible, consomme plus de ressources | Élevé, performances natives |
| Taille de l’installateur | Grande (inclut Chromium) | la plus petite |
Fonctionnalités principales
- Cohérence multiplateforme: L’application s’affiche et se comporte de manière cohérente sur tous les systèmes d’exploitation
- Tirer parti de l’écosystème web: Peut utiliser directement les packages npm et les frameworks Web
- Prototypage rapide: Basé sur des technologies Web familières, cycle de développement court
- API riches: Fournit un ensemble complet d'API pour accéder aux fonctionnalités natives du système
Exemples d'applications pratiques
Créons une application simple de gestionnaire de fichiers pour démontrer l'architecture Electron :
Processus principal (main.js) :
Exemple
const fs = require('fs').promises;
const path = require('path');
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 1000,
height: 700,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true
}
});
mainWindow.loadFile('index.html');
}
// Gérer la lecture de fichier
ipcMain.handle('read-file', async (event, filePath) => {
try {
const content = await fs.readFile(filePath, 'utf-8');
return { success: true, content };
} catch (error) {
return { success: false, error: error.message };
}
});
// Gérer la sélection de fichier
ipcMain.handle('select-file', async () => {
const result = await dialog.showOpenDialog(mainWindow, {
properties: ['openFile'],
filters: [
{ name: 'Fichier texte', extensions: ['txt', 'md', 'js', 'html', 'css'] }
]
});
return result;
});
app.whenReady().then(createWindow);
Script de préchargement (preload.js) :
Exemple
contextBridge.exposeInMainWorld('fileAPI', {
readFile: (filePath) => ipcRenderer.invoke('read-file', filePath),
selectFile: () => ipcRenderer.invoke('select-file')
});
Processus de rendu (index.html) :
Exemple
<html>
<head>
<title>Gestionnaire de fichiers simple</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.container { max-width: 800px; margin: 0 auto; }
button { padding: 10px 15px; margin: 5px; cursor: pointer; }
#content { border: 1px solid #ccc; padding: 15px; margin-top: 10px;
min-height: 300px; white-space: pre-wrap; }
</style>
</head>
<body>
<div class="container">
<h1>Gestionnaire de fichiers simple</h1>
<button id="selectBtn">Sélectionner un fichier</button>
<button id="clearBtn">Effacer le contenu</button>
<div>
<h3>Contenu du fichier :</h3>
<div id="content">Veuillez sélectionner un fichier...</div>
</div>
</div>
<script>
const selectBtn = document.getElementById('selectBtn');
const clearBtn = document.getElementById('clearBtn');
const contentDiv = document.getElementById('content');
selectBtn.addEventListener('click', async () => {
const result = await window.fileAPI.selectFile();
if (!result.canceled && result.filePaths.length > 0) {
const filePath = result.filePaths[0];
const fileResult = await window.fileAPI.readFile(filePath);
if (fileResult.success) {
contentDiv.textContent = `Chemin du fichier : ${filePath}\n\n${fileResult.content}`;
} else {
contentDiv.textContent = `Échec de la lecture du fichier : ${fileResult.error}`;
}
}
});
clearBtn.addEventListener('click', () => {
contentDiv.textContent = 'Veuillez sélectionner un fichier...';
});
</script>
</body>
</html>
Autres modules importants (disponibles dans le processus principal)
| nom du module | Fonction |
|---|---|
app |
Contrôler le cycle de vie de l'application (démarrage/arrêt) |
Menu / MenuItem |
Création de la barre de menus de l'application |
Tray |
Icône de la zone de notification |
Notification |
Notification système |
dialog |
Boîte de dialogue Ouvrir un fichier/Enregistrer |
shell |
Appeler le programme par défaut du système pour ouvrir des fichiers ou des URL |
nativeImage |
Manipuler des images (icônes) |
clipboard |
Manipulation du contenu du presse-papiers |
powerMonitor |
Écouter les événements d'alimentation du système |
screen |
Obtenir des informations sur l'écran (prise en charge multi-écrans) |
Architecture de sécurité et isolation de la sandbox
Étant donné que les processus de rendu peuvent exécuter des pages web, pour empêcher du code malveillant d'attaquer le système, Electron met en œuvre les mécanismes de sécurité suivants :
| Politique | Description |
|---|---|
| Désactiver NodeIntegration | Defaultfalse, évitant ainsi que les pages web appellent directement les API système. |
| Activer ContextIsolation | Faire exécuter les scripts de page et les API Preload dans un contexte isolé. |
| Preload + contextBridge | Contrôler clairement les API sécurisées exposées au frontend. |
| Politique de sécurité du contenu (CSP) | Restreindre les sources de scripts pour prévenir les XSS. |
| mode sandbox | Le sandboxing peut être activé pour isoler complètement le processus de rendu. |
| Valider les URL distantes | Le contenu distant non fiable doit faire l'objet d'une validation par liste blanche. |
Flux d'exécution (du démarrage au rendu)
1、启动应用 (electron .)
↓
2、执行 main.js(主进程启动)
↓
3、app.whenReady() 触发,创建 BrowserWindow
↓
4、BrowserWindow 启动新的渲染进程(Chromium 实例)
↓
5、preload.js 先执行(在隔离上下文中)
↓
6、index.html 加载并显示(运行前端框架)
↓
7、渲染进程通过 IPC 调用主进程逻辑
↓
8、主进程处理请求、返回结果
↓
9、用户关闭窗口 → 主进程监听 → app.quit()
Modèle multi-fenêtres principal-subordonné (multi-processus parallèle)
- Une application Electron n'a toujours qu'un processus principal;
- Mais peut avoirplusieurs processus de rendu (chaque fenêtre est indépendante);
- La communication entre eux doit passer par le relais du processus principal ou utiliser
ipcMain.handleEffectuer un pontage asynchrone.
Schéma :
主进程 (Main) ├── 窗口1 → 渲染进程A (index.html) ├── 窗口2 → 渲染进程B (settings.html) └── 窗口3 → 渲染进程C (dashboard.html)
Composants internes du cœur d'Electron (dépendances sous-jacentes)
| Niveau | Technologie |
|---|---|
| Couche de rendu de l'interface utilisateur | Chromium(Blink + V8) |
| Couche d'interface système | Node.js(libuv + liaisons C++) |
| Couche de gestion des processus | Cœur d'Electron (C++ + JavaScript) |
| Couche de logique applicative | Votre code JS/TS (Main + Renderer) |
autres extensionsVotre code JS s'exécute dans l'environnement Node encapsulé par Electron, tandis que l'interface de rendu s'exécute dans le WebView Chromium.