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 tutorial starter code 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.

avertissement

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 { shell } = require('electron/common')
const { app } = require('electron/main')