Electron : applications de bureau multiplateformes simplifiées
Publié: 2022-03-11Plus tôt cette année, Github a publié Atom-Shell, le cœur de son célèbre éditeur open source Atom, et l'a renommé Electron pour l'occasion spéciale.
Electron, contrairement à d'autres concurrents dans la catégorie des applications de bureau basées sur Node.js, apporte sa propre touche à ce marché déjà bien établi en combinant la puissance de Node.js (io.js jusqu'aux versions récentes) avec le moteur Chromium pour apporter nous le meilleur du JavaScript côté serveur et côté client.
Imaginez un monde où nous pourrions créer des applications de bureau multiplateformes performantes, basées sur les données, alimentées non seulement par le référentiel toujours croissant de modules NPM, mais également par l'ensemble du registre Bower pour répondre à tous nos besoins côté client.
Entrez Électron.
Dans ce didacticiel, nous allons créer une application de trousseau de mot de passe simple à l'aide d'Electron, Angular.js et Loki.js, une base de données légère et en mémoire avec une syntaxe familière pour les développeurs MongoDB.
Le code source complet de cette application est disponible ici.
Ce didacticiel suppose que :
- Le lecteur a installé Node.js et Bower sur sa machine.
- Ils sont familiers avec la syntaxe de requête de type Node.js, Angular.js et MongoDB.
Obtenir les marchandises
Tout d'abord, nous devrons obtenir les fichiers binaires Electron afin de tester notre application localement. Nous pouvons l'installer globalement et l'utiliser comme CLI, ou l'installer localement dans le chemin de notre application. Je recommande de l'installer globalement, afin que nous n'ayons pas à le refaire encore et encore pour chaque application que nous développons.
Nous apprendrons plus tard comment empaqueter notre application pour la distribution en utilisant Gulp. Ce processus implique la copie des fichiers binaires Electron, et il est donc inutile de l'installer manuellement dans le chemin de notre application.
Pour installer la CLI Electron, nous pouvons taper la commande suivante dans notre terminal :
$ npm install -g electron-prebuilt
Pour tester l'installation, tapez electron -h
et il devrait afficher la version de la CLI Electron.
Au moment de la rédaction de cet article, la version d'Electron était la 0.31.2
.
Mise en place du projet
Supposons la structure de dossier de base suivante :
my-app |- cache/ |- dist/ |- src/ |-- app.js | gulpfile.js
… où : - cache/ sera utilisé pour télécharger les binaires Electron lors de la construction de l'application. - dist/ contiendra les fichiers de distribution générés. - src/ contiendra notre code source. - src/app.js sera le point d'entrée de notre application.
Ensuite, nous allons naviguer vers le dossier src/
dans notre terminal et créer les fichiers package.json
et bower.json
pour notre application :
$ npm init $ bower init
Nous installerons les packages nécessaires plus tard dans ce tutoriel.
Comprendre les processus électroniques
Electron distingue deux types de processus :
- Le processus principal : Le point d'entrée de notre application, le fichier qui sera exécuté chaque fois que nous exécuterons l'application. En règle générale, ce fichier déclare les différentes fenêtres de l'application et peut éventuellement être utilisé pour définir des écouteurs d'événements globaux à l'aide du module IPC d'Electron.
- The Renderer Process : Le contrôleur pour une fenêtre donnée dans notre application. Chaque fenêtre crée son propre processus de rendu.
Pour la clarté du code, un fichier séparé doit être utilisé pour chaque processus de rendu. Pour définir le processus principal de notre application, nous allons ouvrir
src/app.js
et inclure le module d'app
pour démarrer l'application, et le module debrowser-window
pour créer les différentes fenêtres de notre application (les deux faisant partie du noyau Electron), en tant que tel:
var app = require('app'), BrowserWindow = require('browser-window');
Lorsque l'application est réellement démarrée, elle déclenche un événement ready
, auquel nous pouvons nous lier. À ce stade, nous pouvons instancier la fenêtre principale de notre application :
var mainWindow = null; app.on('ready', function() { mainWindow = new BrowserWindow({ width: 1024, height: 768 }); mainWindow.loadUrl('file://' + __dirname + '/windows/main/main.html'); mainWindow.openDevTools(); });
Points clés:
- Nous créons une nouvelle fenêtre en créant une nouvelle instance de l'objet
BrowserWindow
. - Il prend un objet comme unique argument, nous permettant de définir différents paramètres, parmi lesquels la largeur et la hauteur par défaut de la fenêtre.
- L'instance de fenêtre a une méthode
loadUrl()
, nous permettant de charger le contenu d'un fichier HTML réel dans la fenêtre actuelle. Le fichier HTML peut être local ou distant . - L'instance de fenêtre a une méthode optionnelle
openDevTools()
, nous permettant d'ouvrir une instance des outils de développement Chrome dans la fenêtre actuelle à des fins de débogage.
Ensuite, nous devrions organiser un peu notre code. Je recommande de créer un dossier windows/
dans notre dossier src/
, et où nous pouvons créer un sous-dossier pour chaque fenêtre, en tant que tel :
my-app |- src/ |-- windows/ |--- main/ |---- main.controller.js |---- main.html |---- main.view.js
… où main.controller.js
contiendra la logique « côté serveur » de notre application, et main.view.js
contiendra la logique « côté client » de notre application.
Le fichier main.html
est simplement une page Web HTML5, nous pouvons donc simplement le démarrer comme ceci :
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Password Keychain</title> </head> <body> <h1>Password Keychain</h1> </body> </html>
À ce stade, notre application devrait être prête à fonctionner. Pour le tester, nous pouvons simplement taper ce qui suit dans notre terminal, à la racine du dossier src
:
$ electron .
Nous pouvons automatiser ce processus en définissant le script de
start
du fichier package.son.
Création d'une application de bureau de trousseau de mot de passe
Pour créer une application de trousseau de mot de passe, nous avons besoin : - D'un moyen d'ajouter, de générer et d'enregistrer des mots de passe. - Un moyen pratique de copier et de supprimer des mots de passe.
Génération et enregistrement de mots de passe
Un simple formulaire suffira pour insérer de nouveaux mots de passe. Afin de démontrer la communication entre plusieurs fenêtres dans Electron, commencez par ajouter une deuxième fenêtre dans notre application, qui affichera le formulaire "insert". Étant donné que nous allons ouvrir et fermer cette fenêtre plusieurs fois, nous devons résumer la logique dans une méthode afin de pouvoir l'appeler simplement en cas de besoin :
function createInsertWindow() { insertWindow = new BrowserWindow({ width: 640, height: 480, show: false }); insertWindow.loadUrl('file://' + __dirname + '/windows/insert/insert.html'); insertWindow.on('closed',function() { insertWindow = null; }); }
Points clés:
- Nous devrons définir la propriété show à false dans l'objet options du constructeur BrowserWindow, afin d'empêcher la fenêtre de s'ouvrir par défaut au démarrage de l'application.
- Nous devrons détruire l'instance BrowserWindow chaque fois que la fenêtre déclenche un événement fermé .
Ouvrir et fermer la fenêtre "Insérer"
L'idée est de pouvoir déclencher la fenêtre "insertion" lorsque l'utilisateur final clique sur un bouton dans la fenêtre "principale". Pour ce faire, nous devrons envoyer un message de la fenêtre principale au processus principal pour lui demander d'ouvrir la fenêtre d'insertion. Nous pouvons y parvenir en utilisant le module IPC d'Electron. Il existe en fait deux variantes du module IPC :
- Un pour le processus principal, permettant à l'application de s'abonner aux messages envoyés depuis Windows.
- Un pour le processus de rendu, permettant à l'application d'envoyer des messages au processus principal.
Bien que le canal de communication d'Electron soit principalement unidirectionnel, il est possible d'accéder au module IPC du processus principal dans un processus de rendu en utilisant le module distant. En outre, le processus principal peut renvoyer un message au processus de rendu à l'origine de l'événement en utilisant la méthode Event.sender.send().
Pour utiliser le module IPC, nous en avons juste besoin comme n'importe quel autre module NPM dans notre script Main Process :
var ipc = require('ipc');
… puis lier aux événements avec la méthode on()
:
ipc.on('toggle-insert-view', function() { if(!insertWindow) { createInsertWindow(); } return (!insertWindow.isClosed() && insertWindow.isVisible()) ? insertWindow.hide() : insertWindow.show(); });
Points clés:
- Nous pouvons nommer l'événement comme nous le voulons, l'exemple est juste arbitraire.
- N'oubliez pas de vérifier si l'instance BrowserWindow est déjà créée, sinon instanciez-la.
- L'instance BrowserWindow a quelques méthodes utiles :
- isClosed() renvoie un booléen, que la fenêtre soit actuellement
closed
ou non. - isVisible() : renvoie un booléen, que la fenêtre soit actuellement visible ou non.
- show() / hide() : méthodes pratiques pour afficher et masquer la fenêtre.
- isClosed() renvoie un booléen, que la fenêtre soit actuellement
Maintenant, nous devons réellement déclencher cet événement à partir du processus de rendu. Nous allons créer un nouveau fichier de script appelé main.view.js
et l'ajouter à notre page HTML comme nous le ferions avec n'importe quel script normal :
<script src="./main.view.js"></script>
Le chargement du fichier de script via la balise de
script
HTML charge ce fichier dans un contexte côté client. Cela signifie que, par exemple, les variables globales sont disponibles viawindow.<varname>
. Pour charger un script dans un contexte côté serveur, nous pouvons utiliser la méthoderequire()
directement dans notre page HTML :require('./main.controller.js');
.
Même si le script est chargé dans un contexte côté client , nous pouvons toujours accéder au module IPC pour le processus de rendu de la même manière que nous pouvons le faire pour le processus principal, puis envoyer notre événement en tant que tel :
var ipc = require('ipc'); angular .module('Utils', []) .directive('toggleInsertView', function() { return function(scope, el) { el.bind('click', function(e) { e.preventDefault(); ipc.send('toggle-insert-view'); }); }; });
Il existe également une méthode sendSync () disponible, au cas où nous aurions besoin d'envoyer nos événements de manière synchrone.
Maintenant, tout ce qu'il nous reste à faire pour ouvrir la fenêtre « insert » est de créer un bouton HTML avec la directive Angular correspondante dessus :
<div ng-controller="MainCtrl as vm"> <button toggle-insert-view class="mdl-button"> <i class="material-icons">add</i> </button> </div>
Et ajoutez cette directive en tant que dépendance du contrôleur angulaire de la fenêtre principale :
angular .module('MainWindow', ['Utils']) .controller('MainCtrl', function() { var vm = this; });
Génération de mots de passe
Pour simplifier les choses, nous pouvons simplement utiliser le module NPM uuid
pour générer des identifiants uniques qui serviront de mots de passe dans le cadre de ce didacticiel. Nous pouvons l'installer comme n'importe quel autre module NPM, l'exiger dans notre script "Utils", puis créer une usine simple qui renverra un identifiant unique :
var uuid = require('uuid'); angular .module('Utils', []) ... .factory('Generator', function() { return { create: function() { return uuid.v4(); } }; })
Maintenant, tout ce qu'il nous reste à faire est de créer un bouton dans la vue d'insertion et d'y attacher une directive qui écoutera les événements de clic sur le bouton et appellera la méthode create() :
<!-- in insert.html --> <button generate-password class="mdl-button">generate</button>
// in Utils.js angular .module('Utils', []) ... .directive('generatePassword', ['Generator', function(Generator) { return function(scope, el) { el.bind('click', function(e) { e.preventDefault(); if(!scope.vm.formData) scope.vm.formData = {}; scope.vm.formData.password = Generator.create(); scope.$apply(); }); }; }])
Enregistrement des mots de passe
À ce stade, nous voulons stocker nos mots de passe. La structure de données pour nos entrées de mot de passe est assez simple :
{ "id": String "description": String, "username": String, "password": String }
Donc, tout ce dont nous avons vraiment besoin est une sorte de base de données en mémoire qui peut éventuellement se synchroniser avec un fichier pour la sauvegarde. Pour cela, Loki.js semble être le candidat idéal. Il fait exactement ce dont nous avons besoin pour les besoins de cette application et offre en plus la fonctionnalité Dynamic Views , nous permettant de faire des choses similaires au module Aggregation de MongoDB.
Les vues dynamiques n'offrent pas toutes les fonctionnalités du module d'agrégation de MongodDB. Veuillez vous référer à la documentation pour plus d'informations.
Commençons par créer un formulaire HTML simple :
<div class="insert" ng-controller="InsertCtrl as vm"> <form name="insertForm" no-validate> <fieldset ng-disabled="!vm.loaded"> <div class="mdl-textfield"> <input class="mdl-textfield__input" type="text" ng-model="vm.formData.description" required /> <label class="mdl-textfield__label" for="description">Description...</label> </div> <div class="mdl-textfield"> <input class="mdl-textfield__input" type="text" ng-model="vm.formData.username" /> <label class="mdl-textfield__label" for="username">Username...</label> </div> <div class="mdl-textfield"> <input class="mdl-textfield__input" type="password" ng-model="vm.formData.password" required /> <label class="mdl-textfield__label" for="password">Password...</label> </div> <div class=""> <button generate-password class="mdl-button">generate</button> <button toggle-insert-view class="mdl-button">cancel</button> <button save-password class="mdl-button" ng-disabled="insertForm.$invalid">save</button> </div> </fieldset> </form> </div>
Et maintenant, ajoutons la logique JavaScript pour gérer la publication et l'enregistrement du contenu du formulaire :

var loki = require('lokijs'), path = require('path'); angular .module('Utils', []) ... .service('Storage', ['$q', function($q) { this.db = new loki(path.resolve(__dirname, '../..', 'app.db')); this.collection = null; this.loaded = false; this.init = function() { var d = $q.defer(); this.reload() .then(function() { this.collection = this.db.getCollection('keychain'); d.resolve(this); }.bind(this)) .catch(function(e) { // create collection this.db.addCollection('keychain'); // save and create file this.db.saveDatabase(); this.collection = this.db.getCollection('keychain'); d.resolve(this); }.bind(this)); return d.promise; }; this.addDoc = function(data) { var d = $q.defer(); if(this.isLoaded() && this.getCollection()) { this.getCollection().insert(data); this.db.saveDatabase(); d.resolve(this.getCollection()); } else { d.reject(new Error('DB NOT READY')); } return d.promise; }; }) .directive('savePassword', ['Storage', function(Storage) { return function(scope, el) { el.bind('click', function(e) { e.preventDefault(); if(scope.vm.formData) { Storage .addDoc(scope.vm.formData) .then(function() { // reset form & close insert window scope.vm.formData = {}; ipc.send('toggle-insert-view'); }); } }); }; }])
Points clés:
- Nous devons d'abord initialiser la base de données. Ce processus implique de créer une nouvelle instance de l'objet Loki, de fournir le chemin d'accès au fichier de base de données en tant qu'argument, de rechercher si ce fichier de sauvegarde existe, de le créer si nécessaire (y compris la collection 'Keychain'), puis de charger le contenu de ce fichier en mémoire.
- Nous pouvons récupérer une collection spécifique dans la base de données avec la méthode
getCollection()
. - Un objet de collection expose plusieurs méthodes, dont une méthode
insert()
, nous permettant d'ajouter un nouveau document à la collection. - Pour conserver le contenu de la base de données dans un fichier, l'objet Loki expose une méthode
saveDatabase()
. - Nous devrons réinitialiser les données du formulaire et envoyer un événement IPC pour indiquer au processus principal de fermer la fenêtre une fois le document enregistré.
Nous avons maintenant un formulaire simple nous permettant de générer et d'enregistrer de nouveaux mots de passe. Revenons à la vue principale pour lister ces entrées.
Liste des mots de passe
Quelques choses doivent se produire ici :
- Nous devons être en mesure d'obtenir tous les documents de notre collection.
- Nous devons informer la vue principale chaque fois qu'un nouveau mot de passe est enregistré afin qu'il puisse actualiser la vue.
Nous pouvons récupérer la liste des documents en appelant la méthode getCollection()
sur l'objet Loki. Cette méthode renvoie un objet avec une propriété appelée data , qui est simplement un tableau de tous les documents de cette collection :
this.getCollection = function() { this.collection = this.db.getCollection('keychain'); return this.collection; }; this.getDocs = function() { return (this.getCollection()) ? this.getCollection().data : null; };
Nous pouvons ensuite appeler getDocs() dans notre contrôleur Angular et récupérer tous les mots de passe stockés dans la base de données, après l'avoir initialisée :
angular .module('MainView', ['Utils']) .controller('MainCtrl', ['Storage', function(Storage) { var vm = this; vm.keychain = null; Storage .init() .then(function(db) { vm.keychain = db.getDocs(); }); });
Un peu de template angulaire, et nous avons une liste de mots de passe :
<tr ng-repeat="item in vm.keychain track by $index" class="item--{{$index}}"> <td class="mdl-data-table__cell--non-numeric">{{item.description}}</td> <td>{{item.username || 'n/a'}}</td> <td> <span ng-repeat="n in [1,2,3,4,5,6]">•</span> </td> <td> <a href="#" copy-password="{{$index}}">copy</a> <a href="#" remove-password="{{item}}">remove</a> </td> </tr>
Une fonctionnalité supplémentaire intéressante serait de rafraîchir la liste des mots de passe après en avoir inséré un nouveau. Pour cela, nous pouvons utiliser le module IPC d'Electron. Comme mentionné précédemment, le module IPC du processus principal peut être appelé dans un processus de rendu pour le transformer en processus d'écoute, en utilisant le module distant. Voici un exemple sur la façon de l'implémenter dans main.view.js
:
var remote = require('remote'), remoteIpc = remote.require('ipc'); angular .module('MainView', ['Utils']) .controller('MainCtrl', ['Storage', function(Storage) { var vm = this; vm.keychain = null; Storage .init() .then(function(db) { vm.keychain = db.getDocs(); remoteIpc.on('update-main-view', function() { Storage .reload() .then(function() { vm.keychain = db.getDocs(); }); }); }); }]);
Points clés:
- Nous devrons utiliser le module distant via sa propre méthode
require()
pour exiger le module IPC distant du processus principal. - Nous pouvons ensuite configurer notre processus de rendu en tant qu'écouteur d'événements via la méthode
on()
et lier les fonctions de rappel à ces événements.
La vue d'insertion se chargera alors de dispatcher cet événement à chaque fois qu'un nouveau document sera enregistré :
Storage .addDoc(scope.vm.formData) .then(function() { // refresh list in main view ipc.send('update-main-view'); // reset form & close insert window scope.vm.formData = {}; ipc.send('toggle-insert-view'); });
Copie des mots de passe
Ce n'est généralement pas une bonne idée d'afficher les mots de passe en texte brut. Au lieu de cela, nous allons masquer et fournir un bouton pratique permettant à l'utilisateur final de copier directement le mot de passe pour une entrée spécifique.
Là encore, Electron vient à notre rescousse en nous fournissant un module presse-papiers avec des méthodes simples pour copier et coller non seulement du contenu textuel, mais aussi des images et du code HTML :
var clipboard = require('clipboard'); angular .module('Utils', []) ... .directive('copyPassword', [function() { return function(scope, el, attrs) { el.bind('click', function(e) { e.preventDefault(); var text = (scope.vm.keychain[attrs.copyPassword]) ? scope.vm.keychain[attrs.copyPassword].password : ''; // atom's clipboard module clipboard.clear(); clipboard.writeText(text); }); }; }]);
Puisque le mot de passe généré sera une simple chaîne, nous pouvons utiliser la méthode writeText()
pour copier le mot de passe dans le presse-papiers du système. Nous pouvons ensuite mettre à jour notre vue principale HTML et ajouter le bouton de copie avec la directive copy-password
dessus, fournissant l'index du tableau de mots de passe :
<a href="#" copy-password="{{$index}}">copy</a>
Suppression de mots de passe
Nos utilisateurs finaux pourraient également souhaiter pouvoir supprimer des mots de passe, au cas où ils deviendraient obsolètes. Pour ce faire, tout ce que nous avons à faire est d'appeler la méthode remove()
sur la collection de trousseaux. Nous devons fournir l'intégralité de la documentation à la méthode 'remove()', en tant que telle :
this.removeDoc = function(doc) { return function() { var d = $q.defer(); if(this.isLoaded() && this.getCollection()) { // remove the doc from the collection & persist changes this.getCollection().remove(doc); this.db.saveDatabase(); // inform the insert view that the db content has changed ipc.send('reload-insert-view'); d.resolve(true); } else { d.reject(new Error('DB NOT READY')); } return d.promise; }.bind(this); };
La documentation Loki.js indique que nous pouvons également supprimer un document par son identifiant, mais cela ne semble pas fonctionner comme prévu.
Création d'un menu de bureau
Electron s'intègre de manière transparente à notre environnement de bureau OS pour fournir une expérience utilisateur «native» à nos applications. Par conséquent, Electron est livré avec un module Menu, dédié à la création de structures de menus de bureau complexes pour notre application.
Le module de menu est un vaste sujet et mériterait presque un tutoriel à lui tout seul. Je vous recommande fortement de lire le didacticiel d'intégration de l'environnement de bureau d'Electron pour découvrir toutes les fonctionnalités de ce module.
Dans le cadre de ce didacticiel actuel, nous verrons comment créer un menu personnalisé, y ajouter une commande personnalisée et implémenter la commande de sortie standard.
Créer et attribuer un menu personnalisé à notre application
En règle générale, la logique JavaScript d'un menu Electron appartiendrait au fichier de script principal de notre application, où notre processus principal est défini. Cependant, nous pouvons l'abstraire dans un fichier séparé et accéder au module Menu via le module distant :
var remote = require('remote'), Menu = remote.require('menu');
Pour définir un menu simple, nous devrons utiliser la méthode buildFromTemplate()
:
var appMenu = Menu.buildFromTemplate([ { label: 'Electron', submenu: [{ label: 'Credits', click: function() { alert('Built with Electron & Loki.js.'); } }] } ]);
Le premier élément du tableau est toujours utilisé comme élément de menu « par défaut ».
La valeur de la propriété
label
n'a pas beaucoup d'importance pour l'élément de menu par défaut. En mode dev, il affichera toujoursElectron
. Nous verrons plus tard comment attribuer un nom personnalisé à l'élément de menu par défaut lors de la phase de construction.
Enfin, nous devons attribuer ce menu personnalisé comme menu par défaut pour notre application avec la méthode setApplicationMenu()
:
Menu.setApplicationMenu(appMenu);
Mappage des raccourcis clavier
Electron fournit des "accélérateurs", un ensemble de chaînes prédéfinies qui correspondent aux combinaisons de clavier réelles, par exemple : Command+A
ou Ctrl+Shift+Z
.
L'accélérateur
Command
ne fonctionne pas sous Windows ou Linux. Pour notre application de trousseau de mots de passe, nous devrions ajouter un élément de menuFile
, proposant deux commandes :
- Créer un mot de passe : ouvrez la vue d'insertion avec Cmd (ou Ctrl) + N
- Quitter : quittez complètement l'application avec Cmd (ou Ctrl) + Q
... { label: 'File', submenu: [ { label: 'Create Password', accelerator: 'CmdOrCtrl+N', click: function() { ipc.send('toggle-insert-view'); } }, { type: 'separator' // to create a visual separator }, { label: 'Quit', accelerator: 'CmdOrCtrl+Q', selector: 'terminate:' // OS X only!!! } ] } ...
Points clés:
- Nous pouvons ajouter un séparateur visuel en ajoutant un élément au tableau avec la propriété
type
définie surseparator
. - L'accélérateur
CmdOrCtrl
est compatible avec les claviers Mac et PC - La propriété
selector
est compatible OSX uniquement !
Styliser notre application
Vous avez probablement remarqué dans les différents exemples de code des références à des noms de classe commençant par mdl-
. Pour les besoins de ce didacticiel, j'ai choisi d'utiliser le framework d'interface utilisateur Material Design Lite, mais n'hésitez pas à utiliser le framework d'interface utilisateur de votre choix.
Tout ce que nous pouvons faire avec HTML5 peut être fait dans Electron ; Gardez simplement à l'esprit la taille croissante des fichiers binaires de l'application et les problèmes de performances qui peuvent survenir si vous utilisez trop de bibliothèques tierces.
Emballage des applications Electron pour la distribution
Vous avez créé une application Electron, elle a fière allure, vous avez écrit vos tests e2e avec Selenium et WebDriver, et vous êtes prêt à la distribuer dans le monde !
Mais vous souhaitez toujours le personnaliser, lui donner un nom personnalisé autre que "Electron" par défaut, et peut-être également fournir des icônes d'application personnalisées pour les plates-formes Mac et PC.
Construire avec Gulp
De nos jours, il existe un plugin Gulp pour tout ce à quoi nous pouvons penser. Tout ce que j'avais à faire était de taper gulp electron
dans Google, et bien sûr il y a un plugin gulp-electron !
Ce plugin est assez facile à utiliser tant que la structure des dossiers détaillée au début de ce tutoriel a été conservée. Sinon, vous devrez peut-être déplacer un peu les choses.
Ce plugin peut être installé comme n'importe quel autre plugin Gulp :
$ npm install gulp-electron --save-dev
Et puis nous pouvons définir notre tâche Gulp comme telle :
var gulp = require('gulp'), electron = require('gulp-electron'), info = require('./src/package.json'); gulp.task('electron', function() { gulp.src("") .pipe(electron({ src: './src', packageJson: info, release: './dist', cache: './cache', version: 'v0.31.2', packaging: true, platforms: ['win32-ia32', 'darwin-x64'], platformResources: { darwin: { CFBundleDisplayName: info.name, CFBundleIdentifier: info.bundle, CFBundleName: info.name, CFBundleVersion: info.version }, win: { "version-string": info.version, "file-version": info.version, "product-version": info.version } } })) .pipe(gulp.dest("")); });
Points clés:
- le dossier
src/
ne peut pas être le même que le dossier où se trouve Gulpfile.js, ni le même dossier que le dossier de distribution. - Nous pouvons définir les plates-formes vers lesquelles nous souhaitons exporter via le tableau
platforms
-formes. - Nous devrions définir un dossier de
cache
, où les binaires Electron seront téléchargés afin qu'ils puissent être empaquetés avec notre application. - Le contenu du fichier package.json de l'application doit être transmis à la tâche gulp via la propriété
packageJson
. - Il existe une propriété d'
packaging
facultative, nous permettant également de créer des archives zip des applications générées. - Pour chaque plate-forme, il existe un ensemble différent de « ressources de plate-forme » qui peuvent être définies.
Ajout d'icônes d'application
L'une des propriétés platformResources
est la propriété icon
, qui nous permet de définir une icône personnalisée pour notre application :
"icon": "keychain.ico"
OS X nécessite des icônes avec l'extension de fichier
.icns
. Il existe plusieurs outils en ligne nous permettant de convertir gratuitement des fichiers.png
en.ico
et.icns
.
Conclusion
Dans cet article, nous n'avons fait qu'effleurer la surface de ce qu'Electron peut réellement faire. Pensez à de grandes applications comme Atom ou Slack comme source d'inspiration où vous pouvez aller avec cet outil.
J'espère que vous avez trouvé ce tutoriel utile, n'hésitez pas à laisser vos commentaires et à partager vos expériences avec Electron !