Aller au contenu principal

Modèle de processus

Electron hérite son architecture multi-processus de Chromium, ce qui rend le framework très similaire dans son architecture à un navigateur web moderne. This guide will expand on the concepts applied in the Tutorial.

Et pourquoi pas un seul processus ?

Les navigateurs Web sont des applications incroyablement compliquées. Outre leur fonction principale d 'affichage de contenu Web, ils ont de nombreuses fonctionnalités secondaires, telles que la gestion de plusieurs fenêtres (ou onglets) et le chargement d’extensions tierces.

Dans les premiers temps, les navigateurs utilisaient généralement un seul processus pour toutes ces fonctionnalités . Bien que ce modèle signifiait moins d'usage de ressource pour chaque onglet ouvert, cela signifiait également que lorsqu'un site Web se plantait cela affectait l'ensemble du navigateur.

Le modèle multi-processus

Pour résoudre ce problème, l'équipe de Chrome a décidé que chaque onglet serait rendu dans son propre processus , limitant ainsi les dommages qu'un code bogué ou malveillant d'une page web pourrait causer à l'application dans son ensemble. Un seul processus de navigateur contrôle ensuite ces processus ainsi que que le cycle de vie de l'application dans son ensemble. Le diagramme ci-dessous issu de la Bd Chrome illustre ce modèle :

Chrome's multi-process architecture

Les applications Electron sont structurées de manière très similaire. En tant que développeur d’applications, vous contrôlez deux types de processus : principal et de rendu. Ceux-ci sont analogues aux propres processus de navigateur et de rendu de Chrome décrits ci-dessus.

Le processus principal

Chaque application Electron ne possède qu'un seul processus principal, celui-ci sert de point d'entrée à l'application. Le processus principal s'exécute dans un environnement Node.js, ce qui signifie qu'il a la capacité d'ajouter des modules à l'aide de require et d'utiliser toutes les API Node.js.

Gestion des fenêtres

The main process' primary purpose is to create and manage application windows with the BrowserWindow module.

Chaque instance de la classe BrowserWindow crée une fenêtre d’application qui charge une page Web dans un processus de rendu distinct. You can interact with this web content from the main process using the window's webContents object.

main.js
const { BrowserWindow } = require('electron')

const win = new BrowserWindow({ width: 800, height: 1500 })
win.loadURL('https://github.com')

const contents = win.webContents
console.log(contents)

Note: A renderer process is also created for web embeds such as the BrowserView module. Et dans de tels cas l’objet webContents est également accessible.

Étant donné que le module BrowserWindow est du type EventEmitter, vous pouvez tout à fait ajouter des gestionnaires pour divers événements utilisateur (par exemple, lors de la réduction ou de l'agrandissement une fenêtre).

Lors de la destruction d’une instance de BrowserWindow, le processus de rendu correspondant est arrêté.

Cycle de vie de l’application

The main process also controls your application's lifecycle through Electron's app module. This module provides a large set of events and methods that you can use to add custom application behavior (for instance, programmatically quitting your application, modifying the application dock, or showing an About panel).

As a practical example, the app shown in the quick start guide uses app APIs to create a more native application window experience.

main.js
//quitter l’application lorsqu’aucune fenêtre n’est ouverte sur les plates-formes non macOS
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})

API natives

Pour étendre les fonctionnalités d’Electron au-delà de celles d'un simple wrapper de Chromium pour du contenu Web, le processus principal ajoute également des API personnalisées pour interagir avec le système d’exploitation de l’utilisateur. Electron expose différents modules qui contrôlent les fonctionnalités de bureau natives, telles que les menus, les boîtes de dialogue et les icônes de la barre de tâches.

Pour une liste complète des modules du processus principal d’Electron, consultez notre documentation de l'API.

Le processus de rendu

Chaque application Electron génère un processus de rendu distinct pour toute BrowserWindow ouverte (ainsi que pour chaque contenu web intégré). Comme son nom l'indique, un moteur de rendu (renderer) est responsable du rendu de contenu web. A toutes fins utiles, le code exécuté dans les processus de rendu devrait se comporter selon les standards web (au moins de la même façon que Chromium).

Par conséquent, toutes les interfaces utilisateur et fonctionnalités de l'application au sein d'une fenêtre seront écrites avec les mêmes outils et paradigmes que vous utilisez pour le Web .

Bien que l'explication de chaque spécification web soit hors de la portée de ce guide, les points suivants représentent le minimum vital pour comprendre:

  • Votre point d'entrée pour le processus de rendu est un fichier HTML.
  • Le style de l'interface utilisateur est ajouté via des feuilles de style (CSS).
  • Le code JavaScript exécutable peut être ajouté via des éléments <script> .

De plus, cela signifie également que le moteur de rendu n’a pas d’accès direct à require ou à d’autres API Node.js. Pour inclure directement des modules NPM dans le moteur de rendu, vous devez utiliser les mêmes chaînes d’outils de groupage (par exemple, webpack ou parcel) que ceux utilisés pour le Web.

attention

Les processus de rendu peuvent être générés avec un environnement Node.js complet pour faciliter le développement . Historiquement, c'était d'ailleurs la valeur par défaut, mais cette fonctionnalité a été désactivée pour des raisons de sécurité.

À ce stade, vous pouvez vous demander comment vos interfaces utilisateur de processus de rendu peuvent interagir avec Node.js et les fonctionnalités natives d'Electron si ces fonctionnalités ne sont accessibles que depuis le processus principal. En fait, il n'y a pas de moyen direct d'importer des scripts de contenu d'Electron.

Scripts de préchargement

Les scripts de préchargement (preload) contiennent du code qui s'exécute dans un processus de rendu (renderer process) avant que son contenu web ne se charge. Ces scripts s’exécutent dans le contexte du moteur de rendu, mais ont des privilèges supplémentaires qui leur donnent accès aux API Node.js.

Un script de préchargement peut être attaché au processus principal à l'aide de l’option webPreferences du constructeur de BrowserWindow .

main.js
const { BrowserWindow } = require('electron')
// ...
const win = new BrowserWindow({
webPreferences: {
preload: 'path/to/preload.js'
}
})
// ...

Comme le script de préchargement partage une interface Window globale avec les moteurs de rendu et peut accéder aux API Node.js, il va être utilisé pour enrichir votre moteur de rendu en exposant des API diverses dans le window global qui seront utilsables ensuite par votre contenu Web.

Although preload scripts share a window global with the renderer they're attached to, you cannot directly attach any variables from the preload script to window because of the contextIsolation default.

preload.js
window.myAPI = {
desktop: true
}
renderer.js
console.log(window.myAPI)
// => undefined

L'isolement du contexte (contextIsolation) implique que les scripts de préchargement sont isolés du monde principal(mainworld) du moteur de rendu pour éviter toute brêche donnant accès à des API privilégiées dans le code de votre contenu web.

Instead, use the contextBridge module to accomplish this securely:

preload.js
const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
desktop: true
})
renderer.js
console.log(window.myAPI)
// => { desktop: true }

Cette fonctionnalité est incroyablement utile pour deux raisons principales:

  • By exposing ipcRenderer helpers to the renderer, you can use inter-process communication (IPC) to trigger main process tasks from the renderer (and vice-versa).
  • Si vous développez un wrapper Electron pour une application web existante hébergée sur une URL distante, vous pouvez ajouter des propriétés personnalisées au window global du moteur de rendu pouvant être utilisées uniquement du côté du client Web de l'appli de bureau.

Utility-process

Each Electron app can spawn multiple child processes from the main process using the UtilityProcess API. Un processus utilitaire s'exécute dans un environnement Node.js, ce qui signifie qu'il a la capacité d'inclure des modules par require et d'utiliser toutes les API Node.js. Un tel processus peut être utilisé pour héberger par exemple : des services non approuvés, des tâches intensives en CPU ou des composants susceptibles de planter qui auraient été précédemment hébergés dans le processus principal ou un processus créé avec l'API de Node.js child_process.fork. La différence principale entre un processus utilitaire et un processus créé par le module child_process de Node.js, est que l'utilitaire peut établir un canal de communication avec un processus de rendu en utilisant MessagePort. An Electron app can always prefer the UtilityProcess API over Node.js child_process.fork API when there is need to fork a child process from the main process.

Alias du module spécifiques au processus (TypeScript)

Le package npm d'Electron exporte également des sous-chemins qui contiennent un sous-ensemble de définitions de type TypeScript d'Electron.

  • electron/main inclut les types pour tous les modules du processus principal.
  • electron/renderer inclut les types pour tous les modules de processus de rendu.
  • electron/common inclut les types de modules pouvant être exécutés dans les processus principaux et de rendu.

Ces alias n'ont aucun impact sur l'exécution, mais peuvent être utilisés pour le controle des types ainsi que l'auto-complétion.

Usage example
const { app } = require('electron/main')
const { shell } = require('electron/common')