Aller au contenu principal

Démarrage Rapide

Ce tutoriel vous guidera dans le processus de création d'une application Hello World dans Electron, similaire à electron/electron-quick-start.

À la fin de ce tutoriel, votre application ouvrira une fenêtre de navigateur qui affichera une page web avec des informations sur les versions de Chromium, de Node.js et d'Electron en cours d'exécution.

Prérequis

Pour utiliser Electron, vous devez installer Node.js. Nous vous recommandons d'utiliser la dernière version LTS disponible.

Veuillez installer Node.js en utilisant des installateurs pré-compilés pour votre plate-forme. Sinon, vous risquez de rencontrer des problèmes d'incompatibilité avec différents outils de développement.

Vous pouvez vérifier que Node.js a été installé correctement en saisissant les commandes suivantes dans votre terminal :

node -v
npm -v

Les commandes devraient afficher respectivement les versions de Node.js et npm.

Remarque : Puisque Electron embarque Node.js dans son binaire, la version de Node.js exécutant votre code n'est pas lié à la version en cours d'exécution sur votre système.

Créer votre application

Initialisation du projet

Les applications Electron suivent la même structure générale que les autres projets Node.js. Commencez par créer un dossier et initialiser un package npm.

mkdir my-electron-app && cd my-electron-app
npm init

La commande interactive init vous demandera de définir quelques champs dans votre configuration. Il y a quelques règles à suivre pour les besoins de ce tutoriel:

  • entry point doit être main.js.
  • author et description peuvent prendre n’importe quelle valeur, mais sont nécessaires pour le packaging de l'application.

Votre fichier package.json devrait ressembler à ceci :

{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"author": "Jane Doe",
"license": "MIT"
}

Ensuite, installez le package electron dans les devDependencies de votre application.

npm install --save-dev electron

Remarque : Si vous rencontrez des problèmes avec l'installation d'Electron, veuillez consulter le guide Installation avancée.

Enfin, comme vous devez pouvoir exécuter Electron. Dans le champ scripts de votre fichier de configuration package.json , ajoutez une commande start comme suit :

{
"scripts": {
"start": "electron ."
}
}

Cette commande start vous permettra d'ouvrir votre application en mode développement.

npm start

Remarque : Ce script indique à Electron de s’exécuter à la racine du dossier de votre projet. À ce stade, votre application va immédiatement lancer une erreur vous disant qu'elle ne trouve pas d'application à exécuter.

Exécuter le processus principal

Le point d’entrée de toute application Electron est son script main. Ce script contrôle le processus principal, qui s'exécute dans un environnement Node.js et gère le cycle de vie de votre application, affiche les interfaces natives, effectue des opérations privilégiées et gére les processus de rendu (plus d'information à ce sujet par la suite).

Pendant l’exécution, Electron va rechercher le nom de ce script dans le champ main du fichier de configuration package.json que vous avez du configurer lors de l’étape Initialisation du projet.

Pour initialiser le script main, créez un fichier vide nommé main.js dans le dossier racine de votre projet.

Remarque : Si vous exécutez à nouveau le script start à ce stade, votre application ne lancera plus d'erreur ! Cependant, elle ne fera rien pour le moment parce que nous n'avons pas ajouté de code dans main.js.

Créer une page Web

Avant de pouvoir créer une fenêtre pour notre application, nous devons créer le contenu qui y sera chargé. Dans Electron, chaque fenêtre affiche le contenu Web qui peut être chargé à partir d'un fichier HTML local ou d'une URL distante.

Pour ce tutoriel, vous allez utiliser la première possibilité. Vous allez donc créer un fichier index.html à la racine de votre projet :

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.
</body>
</html>

Remarque : en regardant ce document HTML, vous pouvez observer que les numéros de version sont absents du texte du body. Nous les insérerons manuellement plus tard à l’aide de JavaScript.

Ouverture de votre page web dans une fenêtre de navigateur

Maintenant que vous avez une page web, chargez-la dans une fenêtre d'application. Pour ce faire, vous aurez besoin de deux modules Electron :

  • Le module app, qui contrôle le cycle de vie des événements de votre application.
  • Le module BrowserWindow, qui crée et gère les fenêtres d’application.

Étant donné que le processus principal exécute Node.js, vous pouvez importer ces derniers en tant que modules CommonJS en haut de votre fichier :

const { app, BrowserWindow } = require('electron')

Ensuite, ajoutez une fonction createWindow() qui charge index.html dans une nouvelle instance BrowserWindow.

const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})

win.loadFile('index.html')
}

Puis, appelez cette fonction createWindow() pour ouvrir votre fenêtre.

Dans Electron, les fenêtres du navigateur ne peuvent être créées qu'après le déclenchement de l’événement ready du module app. Vous pouvez attendre cet événement en utilisant l'API app.whenReady(). Appelez createWindow() une fois que whenReady() a résolu sa Promise.

app.whenReady().then(() => {
createWindow()
})

Remarque : À ce stade, votre application Electron devrait ouvrir avec succès une fenêtre qui affiche votre page web !

Gérer le cycle de vie de votre fenêtre

Bien que vous puissiez maintenant ouvrir une fenêtre de navigateur, vous aurez besoin de code standard supplémentaire pour qu'elle semble plus native pour chaque plate-forme. En effet, les fenêtres d’application se comportent différemment sur chaque système d’exploitation et avec Electron il est de votre responsabilité en tant que développeur d’implémenter leurs conventions dans vos applications.

En général, vous pouvez utiliser l'attribut platform de la variable globale process pour exécuter du code spécifique aux différent systèmes d’exploitation.

Quitter l'application lorsque toutes les fenêtres sont fermées (Windows & Linux)

Sur Windows et Linux, le fait de fermer toutes les fenêtres ferme généralement entièrement l'application.

Pour implémenter cette sortie de l'application vous devez écouter l’événement 'window-all-closed' du module app et appeler app.quit() si l’utilisateur n’est pas sous macOS (darwin).

app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})

Ouvrir une fenêtre si aucune n'est ouverte (macOS)

Alors que les applications Linux et Windows se ferment lorsqu'elles n'ont pas de fenêtres ouvertes, les applications macOS continuent généralement de s'exécuter même sans aucune fenêtre ouverte et activer une application lorsque aucune fenêtre n'est disponible en ouvre une nouvelle.

Pour implémenter cette fonctionnalité, écoutez l'événement activate du module app et appelez votre méthode existante createWindow() si aucune fenêtre de navigateur n'est ouverte.

Étant donné que les fenêtres ne peuvent pas être créées avant l'événement ready , vous ne devriez écouter l'événement activate qu'après l'initialisation de votre application. Pour ce faire, attachez votre event listener à l'intérieur de votre callback whenReady() existante.

app.whenReady().then(() => {
createWindow()

app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

Remarque: À ce stade, vos contrôles de fenêtre doivent être entièrement fonctionnels!

Accéder à Node.js depuis le moteur de rendu avec un script de préchargement

Maintenant, la dernière chose à faire est d'afficher les numéros de version pour Electron et ses dépendances sur votre page web.

L’accès à ces informations est trivial à obtenir dans le processus principal via l’objet global process de Node. Cependant, vous ne pouvez pas simplement modifier le DOM à partir du processus principal car il n'a pas accès au contexte du document du moteur de rendu. Il s'agit en effet de processus entièrement différents!

Note: Si vous avez besoin d'informations approfondies à propos des Processus, veillez consulter la documentation Process Model .

C'est là que l'attachement d'un script preload à votre moteur de rendu est pratique. Un script de préchargement s'exécute avant que le processus de rendu soit chargé, et a accès à la fois aux globales de rendu (c.a.d. window et document) et à l'environnement Node.js.

Création d'un nouveau script nommé preload.js :

window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}

for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})

Le code ci-dessus accède à l'objet process.versions de Node.js et exécute la fonction helper de base replaceText pour insérer les numéros de version dans le document HTML.

Pour attacher ce script à votre processus de rendu, passez le chemin d’accès à votre script de préchargement à l’option webPreferences.preload dans votre constructeur BrowserWindow existant.

// include the Node.js 'path' module at the top of your file
const path = require('path')

// modify your existing createWindow() function
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})

win.loadFile('index.html')
}
// ...

Deux concepts de Node.js sont utilisés ici :

  • La chaîne de caractères __dirname pointe vers le chemin du script en cours d'exécution (dans notre cas, le dossier racine de votre projet).
  • L'API path.join assemble plusieurs parties de path, créant un chemin sous forme d'une chaîne de caractères fonctionnant sur toutes les plateformes.

Nous utilisons un chemin relatif au fichier JavaScript en cours d'exécution afin que votre chemin relatif fonctionne en mode développement et en mode packaged.

Bonus : Ajoutez des fonctionnalités à vos contenus web

À ce stade, vous vous demandez peut êtrer comment ajouter plus de fonctionnalités à votre application.

Pour toute interaction avec votre contenu web, vous souhaitez ajouter des scripts à votre processus de rendu. Parce que le moteur de rendu fonctionne dans un environnement web normal, vous pouvez ajouter une balise <script> juste avant votre balise de fermeture </body> du fichier index.html pour inclure n'importe quel script de votre choix :

<script src="./renderer.js"></script>

Le code contenu dans renderer.js peut alors utiliser les mêmes APIs JavaScript et outils que vous utilisez pour votre développement front-end usuel, comme webpack pour regrouper et minifier votre code ou React pour gérer vos interfaces utilisateur.

Récapitulatif

Après avoir suivi les étapes ci-dessus, vous devriez avoir une application Electron entièrement fonctionnelle ressemblant à ceci :

Application Electron la plus simple

Le code complet est disponible ci-dessous :

// main.js

// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
const path = require('path')

const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})

// et charger l'index.html de l'application.
mainWindow.loadFile('index.html')

// Ouvrir les outils de développement.
// mainWindow.webContents.openDevTools()
}

// Cette méthode sera appelée quand Electron aura fini
// de s'initialiser et sera prêt à créer des fenêtres de navigation.
// Certaines APIs peuvent être utilisées uniquement quant cet événement est émit.
app.whenReady().then(() => {
createWindow()

app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

// Quitter quand toutes les fenêtres sont fermées, sauf sur macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})

// In this file you can include the rest of your app's specific main process
// code. Vous pouvez également le mettre dans des fichiers séparés et les inclure ici.
// preload.js

// All the Node.js APIs are available in the preload process.
// Il a la même sandbox qu'une extension Chrome.
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}

for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})
<!--index.html-->

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.

<!-- Vous pouvez également requérir que d’autres fichiers s’exécutent dans ce processus -->
<script src="./renderer.js"></script>
</body>
</html>
const { app, BrowserWindow } = require('electron')
const path = require('path')

function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})

win.loadFile('index.html')
}

app.whenReady().then(() => {
createWindow()

app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})

app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})

Pour résumer toutes les étapes que nous avons effectuées :

  • Nous avons amorcé une application Node.js et ajouté Electron en tant que dépendance.

  • Nous avons créé un script main.js qui exécute notre processus principal, qui contrôle notre application et s'exécute dans un environnement Node.js. Dans ce script, nous avons utilisé les modules d'Electron app et BrowserWindow pour créer une fenêtre de navigateur qui affiche le contenu web dans un processus séparé (le moteur de rendu).

  • Afin d'accéder à certaines fonctionnalités de Node.js dans le moteur de rendu, nous avons attaché un script de préchargement à notre constructeur BrowserWindow.

Packager et distribuer votre application

Le moyen le plus rapide de distribuer votre nouvelle application est d'utiliser Electron Forge.

  1. Ajoutez Electron Forge en tant que dépendance de développement et utilisez la commande import pour initialiser l'échaffaudage de Forge.

    npm install --save-dev @electron-forge/cli
    npx electron-forge import

    ✔ Checking your system
    ✔ Initializing Git Repository
    ✔ Writing modified package.json file
    ✔ Installing dependencies
    ✔ Writing modified package.json file
    ✔ Fixing .gitignore

    We have ATTEMPTED to convert your app to be in a format that electron-forge understands.

    Thanks for using "electron-forge"!!!
  2. Créez une distribution en utilisant la commande make de Forge :

    npm run make

    > my-electron-app@1.0.0 make /my-electron-app
    > electron-forge make

    ✔ Checking your system
    ✔ Resolving Forge Config
    We need to package your application before we can make it
    ✔ Preparing to Package Application for arch: x64
    ✔ Preparing native dependencies
    ✔ Packaging Application
    Making for the following targets: zip
    ✔ Making for target: zip - On platform: darwin - For arch: x64

    Electron Forge crée le dossier out où se trouvera votre paquet:

    // Example for macOS
    out/
    ├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
    ├── ...
    └── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app