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

// main.js - exemple de processus principal
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

<!-- index.html - exemple de processus de rendu -->
<!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

// preload.js - exemple de script de préchargement
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

const { ipcMain, dialog } = require('electron');

// É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

// Communiquer via l'API exposée par le script de préchargement
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

  1. Cohérence multiplateforme: L’application s’affiche et se comporte de manière cohérente sur tous les systèmes d’exploitation
  2. Tirer parti de l’écosystème web: Peut utiliser directement les packages npm et les frameworks Web
  3. Prototypage rapide: Basé sur des technologies Web familières, cycle de développement court
  4. 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 { app, BrowserWindow, ipcMain, dialog } = require('electron');
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

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('fileAPI', {
  readFile: (filePath) => ipcRenderer.invoke('read-file', filePath),
  selectFile: () => ipcRenderer.invoke('select-file')
});

Processus de rendu (index.html) :

Exemple

<!DOCTYPE html>
<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 utiliseripcMain.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)

Votre 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.

autres extensions