Electron - Guía rápida
¿Por qué Electron?
Electron le permite crear aplicaciones de escritorio con JavaScript puro al proporcionar un tiempo de ejecución con APIs nativas (sistema operativo) ricas.
Esto no significa que Electron sea un enlace de JavaScript para bibliotecas de interfaz gráfica de usuario (GUI). En cambio, Electron usa páginas web como su GUI, por lo que también puede verlo como un navegador Chromium mínimo, controlado por JavaScript. Entonces, todas las aplicaciones electrónicas son técnicamente páginas web que se ejecutan en un navegador que puede aprovechar las API de su sistema operativo.
¿Quién usa Electron?
Github desarrolló Electron para crear el editor de texto Atom. Ambos fueron de código abierto en 2014. Electron es utilizado por muchas empresas como Microsoft, Github, Slack, etc.
Electron se ha utilizado para crear una serie de aplicaciones. A continuación se muestran algunas aplicaciones notables:
- Escritorio flojo
- Aplicación de escritorio Wordpress
- Código de Visual Studio
- Editor de Caret Markdown
- Aplicación de correo electrónico Nylas
- Cliente de git de GitKraken
Para comenzar a desarrollar con Electron, debe tener instalados Node y npm (administrador de paquetes de nodos). Si aún no los tiene, diríjase a la configuración del nodo para instalar el nodo en su sistema local. Confirme que node y npm estén instalados ejecutando los siguientes comandos en su terminal.
node --version
npm --version
El comando anterior generará la siguiente salida:
v6.9.1
3.10.8
Siempre que creamos un proyecto usando npm, necesitamos proporcionar un package.jsonarchivo, que tiene todos los detalles sobre nuestro proyecto. npm nos facilita la configuración de este archivo. Pongamos en marcha nuestro proyecto de desarrollo.
Encienda su terminal / cmd, cree una nueva carpeta llamada hello-world y abra esa carpeta usando el comando cd.
Ahora, para crear el archivo package.json usando npm, use el siguiente comando.
npm init
Le pedirá la siguiente información:
Sigue presionando Enter e ingresa tu nombre en el campo "nombre del autor".
Cree una nueva carpeta y ábrala usando el comando cd. Ahora ejecute el siguiente comando para instalar Electron globalmente.
$ npm install -g electron-prebuilt
Una vez que se ejecuta, puede verificar si Electron está instalado de la manera correcta ejecutando el siguiente comando:
$ electron --version
Deberías obtener el resultado:
v1.4.13
Ahora que hemos configurado Electron, pasemos a crear nuestra primera aplicación usándola.
Electron toma un archivo principal definido en su archivo package.json y lo ejecuta. Este archivo principal crea ventanas de aplicaciones que contienen páginas web renderizadas e interacción con la GUI (interfaz gráfica de usuario) nativa de su sistema operativo.
Al iniciar una aplicación con Electron, main processes creado. Este proceso principal es responsable de interactuar con la GUI nativa del sistema operativo. Crea la GUI de su aplicación.
El simple hecho de iniciar el proceso principal no proporciona a los usuarios de su aplicación ninguna ventana de aplicación. Estos son creados por el proceso principal en el archivo principal usando el módulo BrowserWindow . Cada ventana del navegador ejecuta su propiarenderer process. El proceso del renderizador toma un archivo HTML que hace referencia a los archivos CSS habituales, archivos JavaScript, imágenes, etc. y lo renderiza en la ventana.
El proceso principal puede acceder a la GUI nativa a través de módulos disponibles directamente en Electron. La aplicación de escritorio puede acceder a todos los módulos de nodo como el módulo del sistema de archivos para manejar archivos, solicitar realizar llamadas HTTP, etc.
Diferencia entre los procesos principal y renderizador
El proceso principal crea páginas web mediante la creación de instancias de BrowserWindow . Cada instancia de BrowserWindow ejecuta la página web en su propio proceso de representación. Cuando se destruye una instancia de BrowserWindow , el proceso de renderizado correspondiente también finaliza.
El proceso principal gestiona todas las páginas web y sus correspondientes procesos de renderizado. Cada proceso de renderizado está aislado y solo se preocupa por la página web que se ejecuta en él.
Hemos creado un package.jsonarchivo para nuestro proyecto. Ahora crearemos nuestra primera aplicación de escritorio usando Electron.
Crear un nuevo archivo llamado main.js . Ingrese el siguiente código en él:
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Cree otro archivo, esta vez un archivo HTML llamado index.html . Ingrese el siguiente código en él.
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</body>
</html>
Ejecute esta aplicación con el siguiente comando:
$ electron ./main.js
Se abrirá una nueva ventana. Se verá así:
¿Cómo funciona esta aplicación?
Creamos un archivo principal y un archivo HTML. El archivo principal utiliza dos módulos: app y BrowserWindow . El módulo de la aplicación se usa para controlar el ciclo de vida de eventos de su aplicación, mientras que el módulo BrowserWindow se usa para crear y controlar las ventanas del navegador.
Definimos una función createWindow , donde estamos creando una nueva BrowserWindow y adjuntando una URL a esta BrowserWindow. Este es el archivo HTML que se representa y se nos muestra cuando ejecutamos la aplicación.
Hemos utilizado un proceso de objeto nativo de Electron en nuestro archivo html. Este objeto se extiende desde el objeto de proceso Node.js e incluye todos lost=its funcionalidades al tiempo que agrega muchas más.
La interfaz de usuario de las aplicaciones Electron se crea utilizando HTML, CSS y JS. Así que aquí también podemos aprovechar todas las herramientas disponibles para el desarrollo web front-end. Puede utilizar herramientas como Angular, Backbone, React, Bootstrap y Foundation para crear las aplicaciones.
Puede usar Bower para administrar estas dependencias de front-end. Instale bower usando -
$ npm install -g bower
Ahora puede obtener todos los marcos, bibliotecas, complementos, etc. de JS y CSS disponibles utilizando bower. Por ejemplo, para obtener la última versión estable de bootstrap, ingrese el siguiente comando:
$ bower install bootstrap
Esto descargará bootstrap en bower_components . Ahora puede hacer referencia a esta biblioteca en su HTML. Creemos una página simple usando estas bibliotecas.
Instalemos ahora jquery usando el comando npm -
$ npm install --save jquery
Además, esto será necesario en nuestro archivo view.js. Ya tenemos una configuración main.js de la siguiente manera:
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Abre tu index.html archivo e ingrese el siguiente código en él -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Hello World!</title>
<link rel = "stylesheet"
href = "./bower_components/bootstrap/dist/css/bootstrap.min.css" />
</head>
<body>
<div class = "container">
<h1>This page is using Bootstrap and jQuery!</h1>
<h3 id = "click-counter"></h3>
<button class = "btn btn-success" id = "countbtn">Click here</button>
<script src = "./view.js" ></script>
</div>
</body>
</html>
Crear view.js e ingrese la lógica del contador de clics en él -
let $ = require('jquery') // jQuery now loaded and assigned to $
let count = 0
$('#click-counter').text(count.toString())
$('#countbtn').on('click', () => {
count ++
$('#click-counter').text(count)
})
Ejecute la aplicación usando el siguiente comando:
$ electron ./main.js
El comando anterior generará la salida como en la siguiente captura de pantalla:
Puede crear su aplicación nativa del mismo modo que crea sitios web. Si no desea que los usuarios estén restringidos a un tamaño de ventana exacto, puede aprovechar el diseño receptivo y permitir que los usuarios usen su aplicación de manera flexible.
El manejo de archivos es una parte muy importante de la creación de una aplicación de escritorio. Casi todas las aplicaciones de escritorio interactúan con archivos.
Crearemos un formulario en nuestra aplicación que tomará como entrada, un Nombre y una Dirección de correo electrónico. Este formulario se guardará en un archivo y se creará una lista que mostrará esto como salida.
Configure su proceso principal usando el siguiente código en el main.js archivo -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Ahora abre el index.html archivo e ingrese el siguiente código en él -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>File System</title>
<link rel = "stylesheet"
href = "./bower_components/bootstrap/dist/css/bootstrap.min.css" />
<style type = "text/css">
#contact-list {
height: 150px;
overflow-y: auto;
}
</style>
</head>
<body>
<div class = "container">
<h1>Enter Names and Email addresses of your contacts</h1>
<div class = "form-group">
<label for = "Name">Name</label>
<input type = "text" name = "Name" value = "" id = "Name"
placeholder = "Name" class = "form-control" required>
</div>
<div class = "form-group">
<label for = "Email">Email</label>
<input type = "email" name = "Email" value = "" id = "Email"
placeholder = "Email" class = "form-control" required>
</div>
<div class = "form-group">
<button class = "btn btn-primary" id = "add-to-list">Add to list!</button>
</div>
<div id = "contact-list">
<table class = "table-striped" id = "contact-table">
<tr>
<th class = "col-xs-2">S. No.</th>
<th class = "col-xs-4">Name</th>
<th class = "col-xs-6">Email</th>
</tr>
</table>
</div>
<script src = "./view.js" ></script>
</div>
</body>
</html>
Ahora debemos manejar el evento de suma. Haremos esto en nuestroview.js archivo.
Crearemos una función loadAndDisplayContacts () que inicialmente cargará contactos desde el archivo. Después de crear la función loadAndDisplayContacts () , crearemos un controlador de clic en nuestroadd to listbotón. Esto agregará la entrada tanto al archivo como a la tabla.
En su archivo view.js, ingrese el siguiente código:
let $ = require('jquery')
let fs = require('fs')
let filename = 'contacts'
let sno = 0
$('#add-to-list').on('click', () => {
let name = $('#Name').val()
let email = $('#Email').val()
fs.appendFile('contacts', name + ',' + email + '\n')
addEntry(name, email)
})
function addEntry(name, email) {
if(name && email) {
sno++
let updateString = '<tr><td>'+ sno + '</td><td>'+ name +'</td><td>'
+ email +'</td></tr>'
$('#contact-table').append(updateString)
}
}
function loadAndDisplayContacts() {
//Check if file exists
if(fs.existsSync(filename)) {
let data = fs.readFileSync(filename, 'utf8').split('\n')
data.forEach((contact, index) => {
let [ name, email ] = contact.split(',')
addEntry(name, email)
})
} else {
console.log("File Doesn\'t Exist. Creating new file.")
fs.writeFile(filename, '', (err) => {
if(err)
console.log(err)
})
}
}
loadAndDisplayContacts()
Ahora ejecute la aplicación, usando el siguiente comando:
$ electron ./main.js
Una vez que le agregue algunos contactos, la aplicación se verá así:
Para más fs module API calls, consulte el tutorial del sistema de archivos de nodo .
Ahora podemos manejar archivos usando Electron. Veremos cómo llamar a los cuadros de diálogo guardar y abrir (nativos) para archivos en el capítulo de diálogos.
Usamos un módulo de nodo, fs, en el capítulo anterior. Ahora veremos algunos otros módulos de nodo que podemos usar con Electron.
Módulo OS
Al usar el módulo del sistema operativo, podemos obtener mucha información sobre el sistema en el que se ejecuta nuestra aplicación. A continuación, se muestran algunos métodos que ayudan mientras se crea la aplicación. Estos métodos nos ayudan a personalizar las aplicaciones de acuerdo con el sistema operativo en el que se ejecutan.
No Señor | Función descriptiva |
---|---|
1 | os.userInfo([options]) los os.userInfo()El método devuelve información sobre el usuario efectivo actualmente. Esta información se puede utilizar para personalizar la aplicación para el usuario incluso sin pedir información explícitamente. |
2 | os.platform() los os.platform()El método devuelve una cadena que identifica la plataforma del sistema operativo. Esto se puede utilizar para personalizar la aplicación según el sistema operativo del usuario. |
3 | os.homedir() los os.homedir()El método devuelve el directorio de inicio del usuario actual como una cadena. Generalmente, las configuraciones de todos los usuarios residen en el directorio de inicio del usuario. Así que esto se puede utilizar con el mismo propósito para nuestra aplicación. |
4 | os.arch() los os.arch()El método devuelve una cadena que identifica la arquitectura de la CPU del sistema operativo. Esto se puede utilizar cuando se ejecuta en arquitecturas exóticas para adaptar su aplicación a ese sistema. |
5 | os.EOL Una constante de cadena que define el marcador de fin de línea específico del sistema operativo. Esto debe usarse siempre que terminen líneas en archivos en el sistema operativo host. |
Usando el mismo archivo main.js y el siguiente archivo HTML, podemos imprimir estas propiedades en la pantalla:
<html>
<head>
<title>OS Module</title>
</head>
<body>
<script>
let os = require('os')
document.write('User Info: ' + JSON.stringify(os.userInfo()) + '<br>' +
'Platform: ' + os.platform() + '<br>' +
'User home directory: ' + os.homedir() + '<br>' +
'OS Architecture: ' + os.arch() + '<br>')
</script>
</body>
</html>
Ahora ejecute la aplicación usando el siguiente comando:
$ electron ./main.js
El comando anterior generará la siguiente salida:
User Info: {"uid":1000,"gid":1000,"username":"ayushgp","homedir":"/home/ayushgp",
"shell":"/usr/bin/zsh"}
Platform: linux
User home directory: /home/ayushgp
OS Architecture: x64
Módulo de red
El módulo de red se utiliza para trabajos relacionados con la red en la aplicación. Podemos crear tanto servidores como conexiones de socket usando este módulo. En general, se recomienda el uso del módulo contenedor de npm sobre el uso del módulo net para tareas relacionadas con la red.
Las siguientes tablas enumeran los métodos más útiles del módulo:
No Señor | Función descriptiva |
---|---|
1 | net.createServer([options][, connectionListener]) Crea un nuevo servidor TCP. El argumento connectionListener se establece automáticamente como un oyente para el evento 'connection'. |
2 | net.createConnection(options[, connectionListener]) Un método de fábrica, que devuelve un nuevo 'net.Socket' y se conecta a la dirección y al puerto proporcionados. |
3 | net.Server.listen(port[, host][, backlog][, callback]) Comience a aceptar conexiones en el puerto y host especificados. Si se omite el host, el servidor aceptará conexiones dirigidas a cualquier dirección IPv4. |
4 | net.Server.close([callback]) Finalmente se cierra cuando se terminan todas las conexiones y el servidor emite un evento de "cierre". |
5 | net.Socket.connect(port[, host][, connectListener]) Abre la conexión para un enchufe determinado. Si se proporcionan el puerto y el host, el conector se abrirá como un conector TCP. |
El módulo de red también viene con algunos otros métodos. Para obtener una lista más completa, vea esto .
Ahora, creemos una aplicación electrónica que use el módulo net para crear conexiones con el servidor. Necesitaremos crear un nuevo archivo,server.js -
var net = require('net');
var server = net.createServer(function(connection) {
console.log('Client Connected');
connection.on('end', function() {
console.log('client disconnected');
});
connection.write('Hello World!\r\n');
connection.pipe(connection);
});
server.listen(8080, function() {
console.log('Server running on http://localhost:8080');
});
Usando el mismo archivo main.js, reemplace el archivo HTML con lo siguiente:
<html>
<head>
<title>net Module</title>
</head>
<body>
<script>
var net = require('net');
var client = net.connect({port: 8080}, function() {
console.log('Connection established!');
});
client.on('data', function(data) {
document.write(data.toString());
client.end();
});
client.on('end', function() {
console.log('Disconnected :(');
});
</script>
</body>
</html>
Ejecute el servidor con el siguiente comando:
$ node server.js
Ejecute la aplicación usando el siguiente comando:
$ electron ./main.js
El comando anterior generará la siguiente salida:
Observe que nos conectamos al servidor automáticamente y también nos desconectamos automáticamente.
También tenemos algunos otros módulos de nodo que podemos usar directamente en el front-end usando Electron. El uso de estos módulos depende del escenario en el que los use.
Electron nos proporciona 2 módulos IPC (comunicación entre procesos) llamados ipcMain y ipcRenderer.
los ipcMainEl módulo se utiliza para comunicarse de forma asincrónica desde el proceso principal a los procesos del renderizador. Cuando se usa en el proceso principal, el módulo maneja los mensajes asíncronos y síncronos enviados desde un proceso de renderizado (página web). Los mensajes enviados desde un renderizador se emitirán a este módulo.
los ipcRendererEl módulo se utiliza para comunicarse de forma asincrónica desde un proceso de renderizado al proceso principal. Proporciona algunos métodos para que pueda enviar mensajes sincrónicos y asincrónicos desde el proceso del renderizador (página web) al proceso principal. También puede recibir respuestas del proceso principal.
Crearemos un proceso principal y un proceso de renderizado que se enviarán mensajes entre sí utilizando los módulos anteriores.
Crea un nuevo archivo llamado main_process.js con los siguientes contenidos -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
const {ipcMain} = require('electron')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
// Event handler for asynchronous incoming messages
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg)
// Event emitter for sending asynchronous messages
event.sender.send('asynchronous-reply', 'async pong')
})
// Event handler for synchronous incoming messages
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg)
// Synchronous event emmision
event.returnValue = 'sync pong'
})
app.on('ready', createWindow)
Ahora crea un nuevo index.html archivo y agregue el siguiente código en él.
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Hello World!</title>
</head>
<body>
<script>
const {ipcRenderer} = require('electron')
// Synchronous message emmiter and handler
console.log(ipcRenderer.sendSync('synchronous-message', 'sync ping'))
// Async message handler
ipcRenderer.on('asynchronous-reply', (event, arg) => {
console.log(arg)
})
// Async message sender
ipcRenderer.send('asynchronous-message', 'async ping')
</script>
</body>
</html>
Ejecute la aplicación usando el siguiente comando:
$ electron ./main_process.js
El comando anterior generará la siguiente salida:
// On your app console
Sync Pong
Async Pong
// On your terminal where you ran the app
Sync Ping
Async Ping
Se recomienda no realizar el cálculo de tareas pesadas / de bloqueo en el proceso de renderizado. Utilice siempre IPC para delegar estas tareas al proceso principal. Esto ayuda a mantener el ritmo de su aplicación.
Es muy importante que cualquier aplicación sea fácil de usar. Como resultado, no debe crear cuadros de diálogo utilizando llamadas alert (). Electron proporciona una interfaz bastante buena para realizar la tarea de crear cuadros de diálogo. Echemos un vistazo.
Electron proporciona un dialog módulo que podemos usar para mostrar los diálogos nativos del sistema para abrir y guardar archivos, alertas, etc.
Pasemos directamente a un ejemplo y creemos una aplicación para mostrar archivos de texto simples.
Cree un nuevo archivo main.js e ingrese el siguiente código en él:
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
const {ipcMain} = require('electron')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
ipcMain.on('openFile', (event, path) => {
const {dialog} = require('electron')
const fs = require('fs')
dialog.showOpenDialog(function (fileNames) {
// fileNames is an array that contains all the selected
if(fileNames === undefined) {
console.log("No file selected");
} else {
readFile(fileNames[0]);
}
});
function readFile(filepath) {
fs.readFile(filepath, 'utf-8', (err, data) => {
if(err){
alert("An error ocurred reading the file :" + err.message)
return
}
// handle the file content
event.sender.send('fileData', data)
})
}
})
app.on('ready', createWindow)
Este código abrirá el cuadro de diálogo de apertura cada vez que nuestro proceso principal reciba un mensaje 'openFile' de un proceso de renderizado. Este mensaje redirigirá el contenido del archivo al proceso de renderizado. Ahora tendremos que imprimir el contenido.
Ahora, crea un nuevo index.html archivo con el siguiente contenido -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>File read using system dialogs</title>
</head>
<body>
<script type = "text/javascript">
const {ipcRenderer} = require('electron')
ipcRenderer.send('openFile', () => {
console.log("Event sent.");
})
ipcRenderer.on('fileData', (event, data) => {
document.write(data)
})
</script>
</body>
</html>
Ahora, cada vez que ejecutamos nuestra aplicación, aparecerá un cuadro de diálogo abierto nativo como se muestra en la siguiente captura de pantalla:
Una vez que seleccionamos un archivo para mostrar, su contenido se mostrará en la ventana de la aplicación:
Este fue solo uno de los cuatro diálogos que proporciona Electron. Sin embargo, todos tienen un uso similar. Una vez que aprenda a hacerlo usandoshowOpenDialog, luego puede usar cualquiera de los otros cuadros de diálogo.
Los cuadros de diálogo que tienen la misma funcionalidad son:
- showSaveDialog ([browserWindow,] opciones [, callback])
- showMessageDialog ([browserWindow,] opciones [, callback])
- showErrorDialog (título, contenido)
Las aplicaciones de escritorio vienen con dos tipos de menús: el application menu(en la barra superior) y un context menu(menú contextual). Aprenderemos cómo crear ambos en este capítulo.
Usaremos dos módulos: los módulos Menú y MenuItem . Tenga en cuenta que los módulos Menu y MenuItem solo están disponibles en el proceso principal. Para usar estos módulos en el proceso de renderizado, necesita el módulo remoto . Nos encontraremos con esto cuando creemos un menú contextual.
Ahora, creemos un nuevo main.js archivo para el proceso principal -
const {app, BrowserWindow, Menu, MenuItem} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
const template = [
{
label: 'Edit',
submenu: [
{
role: 'undo'
},
{
role: 'redo'
},
{
type: 'separator'
},
{
role: 'cut'
},
{
role: 'copy'
},
{
role: 'paste'
}
]
},
{
label: 'View',
submenu: [
{
role: 'reload'
},
{
role: 'toggledevtools'
},
{
type: 'separator'
},
{
role: 'resetzoom'
},
{
role: 'zoomin'
},
{
role: 'zoomout'
},
{
type: 'separator'
},
{
role: 'togglefullscreen'
}
]
},
{
role: 'window',
submenu: [
{
role: 'minimize'
},
{
role: 'close'
}
]
},
{
role: 'help',
submenu: [
{
label: 'Learn More'
}
]
}
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
app.on('ready', createWindow)
Estamos creando un menú a partir de una plantilla aquí. Esto significa que proporcionamos el menú como JSON a la función y ella se encargará del resto. Ahora tenemos que configurar este menú como menú de aplicaciones.
Ahora cree un archivo HTML vacío llamado index.html y ejecute esta aplicación usando -
$ electron ./main.js
En la posición normal de los menús de la aplicación, verá un menú basado en la plantilla anterior.
Creamos este menú a partir del proceso principal. Creemos ahora un menú contextual para nuestra aplicación. Haremos esto en nuestro archivo HTML -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Menus</title>
</head>
<body>
<script type = "text/javascript">
const {remote} = require('electron')
const {Menu, MenuItem} = remote
const menu = new Menu()
// Build menu one item at a time, unlike
menu.append(new MenuItem ({
label: 'MenuItem1',
click() {
console.log('item 1 clicked')
}
}))
menu.append(new MenuItem({type: 'separator'}))
menu.append(new MenuItem({label: 'MenuItem2', type: 'checkbox', checked: true}))
menu.append(new MenuItem ({
label: 'MenuItem3',
click() {
console.log('item 3 clicked')
}
}))
// Prevent default action of right click in chromium. Replace with our menu.
window.addEventListener('contextmenu', (e) => {
e.preventDefault()
menu.popup(remote.getCurrentWindow())
}, false)
</script>
</body>
</html>
Importamos los módulos Menu y MenuItem usando el módulo remoto; luego, creamos un menú y le agregamos nuestros elementos de menú uno por uno. Además, evitamos la acción predeterminada de hacer clic con el botón derecho en cromo y la reemplazamos con nuestro menú.
La creación de menús en Electron es una tarea muy sencilla. Ahora puede adjuntar sus controladores de eventos a estos elementos y manejar los eventos de acuerdo con sus necesidades.
La bandeja del sistema es un menú fuera de la ventana de la aplicación. En MacOS y Ubuntu, se encuentra en la esquina superior derecha de la pantalla. En Windows, está en la esquina inferior derecha. Podemos crear menús para nuestra aplicación en bandejas del sistema usando Electron.
Crear un nuevo main.jsarchivo y agregue el siguiente código. Tenga un archivo png listo para usar para el icono de la bandeja del sistema.
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Después de haber configurado una ventana básica del navegador, crearemos una nueva index.html archivo con el siguiente contenido -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Menus</title>
</head>
<body>
<script type = "text/javascript">
const {remote} = require('electron')
const {Tray, Menu} = remote
const path = require('path')
let trayIcon = new Tray(path.join('','/home/ayushgp/Desktop/images.png'))
const trayMenuTemplate = [
{
label: 'Empty Application',
enabled: false
},
{
label: 'Settings',
click: function () {
console.log("Clicked on settings")
}
},
{
label: 'Help',
click: function () {
console.log("Clicked on Help")
}
}
]
let trayMenu = Menu.buildFromTemplate(trayMenuTemplate)
trayIcon.setContextMenu(trayMenu)
</script>
</body>
</html>
Creamos la bandeja usando el submódulo Tray. Luego creamos un menú usando una plantilla y luego adjuntamos el menú a nuestro objeto de bandeja.
Ejecute la aplicación usando el siguiente comando:
$ electron ./main.js
Cuando ejecute el comando anterior, verifique en la bandeja del sistema el icono que utilizó. Usé una carita sonriente para mi solicitud. El comando anterior generará la siguiente salida:
Electron proporciona API de notificaciones nativas solo para MacOS. Entonces no vamos a usar eso, en su lugar usaremos un módulo npm llamado notificador de nodo . Nos permite notificar a los usuarios en Windows, MacOS y Linux.
Instale el módulo notificador de nodos en la carpeta de su aplicación usando el siguiente comando en esa carpeta:
$ npm install --save node-notifier
Creemos ahora una aplicación que tenga un botón que generará una notificación cada vez que hagamos clic en este botón.
Crear un nuevo main.js archivo e ingrese el siguiente código en él -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Creemos ahora nuestra página web y el script que activará la notificación. Crear un nuevoindex.html archivo con el siguiente código -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Menus</title>
</head>
<body>
<button type = "button" id = "notify" name = "button">
Click here to trigger a notification!</button>
<script type = "text/javascript">
const notifier = require('node-notifier')
const path = require('path');
document.getElementById('notify').onclick = (event) => {
notifier.notify ({
title: 'My awesome title',
message: 'Hello from electron, Mr. User!',
icon: path.join('','/home/ayushgp/Desktop/images.png'), // Absolute path
(doesn't work on balloons)
sound: true, // Only Notification Center or Windows Toasters
wait: true // Wait with callback, until user action is taken
against notification
}, function (err, response) {
// Response is response from notification
});
notifier.on('click', function (notifierObject, options) {
console.log("You clicked on the notification")
});
notifier.on('timeout', function (notifierObject, options) {
console.log("Notification timed out!")
});
}
</script>
</body>
</html>
los notify El método nos permite pasarlo un objectwithinformación como el título, mensaje, miniatura, etc. que nos ayudan a personalizar la notificación. También podemos configurar algunos detectores de eventos en la notificación.
Ahora, ejecute la aplicación usando el siguiente comando:
$ electron ./main.js
Cuando haga clic en el botón que creamos, verá una notificación nativa de su sistema operativo como se muestra en la siguiente captura de pantalla:
También hemos manejado los eventos en los que el usuario hace clic en la notificación o la notificación se agota. Estos métodos nos ayudan a hacer que la aplicación sea más interactiva si se ejecuta en segundo plano.
La etiqueta webview se utiliza para incrustar el contenido de 'invitado', como páginas web, en su aplicación Electron. Este contenido está incluido en el contenedor de vistas web. Una página incorporada dentro de su aplicación controla cómo se mostrará este contenido.
La vista web se ejecuta en un proceso diferente al de su aplicación. Para garantizar la seguridad contra contenido malicioso, la vista web no tiene los mismos permisos que su página web. Esto mantiene su aplicación a salvo del contenido incrustado. Todas las interacciones entre su aplicación y la página insertada serán asincrónicas.
Consideremos un ejemplo para comprender la incrustación de una página web externa en nuestra aplicación Electron. Integraremos el sitio web tutorialspoint en nuestra aplicación en el lado derecho. Crear un nuevomain.js archivo con el siguiente contenido -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Ahora que hemos configurado nuestro proceso principal, creemos el archivo HTML que incrustará el sitio web de tutorialspoint. Cree un archivo llamado index.html con el siguiente contenido:
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Menus</title>
</head>
<body>
<div>
<div>
<h2>We have the website embedded below!</h2>
</div>
<webview id = "foo" src = "https://www.tutorialspoint.com/" style =
"width:400px; height:480px;">
<div class = "indicator"></div>
</webview>
</div>
<script type = "text/javascript">
// Event handlers for loading events.
// Use these to handle loading screens, transitions, etc
onload = () => {
const webview = document.getElementById('foo')
const indicator = document.querySelector('.indicator')
const loadstart = () => {
indicator.innerText = 'loading...'
}
const loadstop = () => {
indicator.innerText = ''
}
webview.addEventListener('did-start-loading', loadstart)
webview.addEventListener('did-stop-loading', loadstop)
}
</script>
</body>
</html>
Ejecute la aplicación usando el siguiente comando:
$ electron ./main.js
El comando anterior generará la siguiente salida:
La etiqueta webview también se puede utilizar para otros recursos. El elemento webview tiene una lista de eventos que emite enumerados en los documentos oficiales. Puede utilizar estos eventos para mejorar la funcionalidad en función de las cosas que suceden en la vista web.
Siempre que incorpore scripts u otros recursos de Internet, es recomendable utilizar webview. Esto se recomienda ya que ofrece grandes beneficios de seguridad y no obstaculiza el comportamiento normal.
La captura de audio y video son características importantes si está creando aplicaciones para compartir pantalla, notas de voz, etc. También son útiles si necesita una aplicación para capturar la imagen de perfil.
Usaremos la API HTML5 de getUserMedia para capturar transmisiones de audio y video con Electron. Primero configuremos nuestro proceso principal en elmain.js archivo de la siguiente manera:
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
// Set the path where recordings will be saved
app.setPath("userData", __dirname + "/saved_recordings")
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
Ahora que hemos configurado nuestro proceso principal, creemos el archivo HTML que capturará este contenido. Crea un archivo llamadoindex.html con el siguiente contenido -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Audio and Video</title>
</head>
<body>
<video autoplay></video>
<script type = "text/javascript">
function errorCallback(e) {
console.log('Error', e)
}
navigator.getUserMedia({video: true, audio: true}, (localMediaStream) => {
var video = document.querySelector('video')
video.src = window.URL.createObjectURL(localMediaStream)
video.onloadedmetadata = (e) => {
// Ready to go. Do some stuff.
};
}, errorCallback)
</script>
</body>
</html>
El programa anterior generará la siguiente salida:
Ahora tiene la transmisión tanto de su cámara web como de su micrófono. Puede enviar esta transmisión a través de la red o guardarla en el formato que desee.
Eche un vistazo a la documentación de MDN para capturar imágenes para obtener las imágenes de su cámara web y almacenarlas. Esto se hizo utilizando la API getUserMedia de HTML5 . También puede capturar el escritorio del usuario utilizando el módulo desktopCapturer que viene con Electron. Veamos ahora un ejemplo de cómo obtener el flujo de pantalla.
Use el mismo archivo main.js que el anterior y edite el archivo index.html para que tenga el siguiente contenido:
desktopCapturer.getSources({types: ['window', 'screen']}, (error, sources) => {
if (error) throw error
for (let i = 0; i < sources.length; ++i) {
if (sources[i].name === 'Your Window Name here!') {
navigator.webkitGetUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: sources[i].id,
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720
}
}
}, handleStream, handleError)
return
}
}
})
function handleStream (stream) {
document.querySelector('video').src = URL.createObjectURL(stream)
}
function handleError (e) {
console.log(e)
}
Hemos utilizado el módulo desktopCapturer para obtener la información sobre cada ventana abierta. Ahora puedes capturar los eventos de una aplicación específica o de toda la pantalla dependiendo del nombre que le pases a la anteriorif statement. Esto transmitirá solo lo que está sucediendo en esa pantalla a su aplicación.
Puede consultar esta pregunta de StackOverflow para comprender el uso en detalle.
Por lo general, hemos memorizado ciertos atajos para todas las aplicaciones que usamos en nuestra PC a diario. Para que sus aplicaciones se sientan intuitivas y de fácil acceso para el usuario, debe permitir que el usuario use atajos.
Usaremos el módulo globalShortcut para definir accesos directos en nuestra aplicación. Tenga en cuenta queAcceleratorsson cadenas que pueden contener varios modificadores y códigos de tecla, combinados con el carácter +. Estos aceleradores se utilizan para definir atajos de teclado en toda nuestra aplicación.
Consideremos un ejemplo y creemos un atajo. Para ello, seguiremos el ejemplo de los cuadros de diálogo donde usamos el cuadro de diálogo abrir para abrir archivos. Registraremos unCommandOrControl+O atajo para abrir el cuadro de diálogo.
Nuestra main.jsEl código seguirá siendo el mismo que antes. Así que crea un nuevomain.js archivo e ingrese el siguiente código en él -
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
const {ipcMain} = require('electron')
let win
function createWindow() {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format ({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
ipcMain.on('openFile', (event, path) => {
const {dialog} = require('electron')
const fs = require('fs')
dialog.showOpenDialog(function (fileNames) {
// fileNames is an array that contains all the selected
if(fileNames === undefined)
console.log("No file selected")
else
readFile(fileNames[0])
})
function readFile(filepath){
fs.readFile(filepath, 'utf-8', (err, data) => {
if(err){
alert("An error ocurred reading the file :" + err.message)
return
}
// handle the file content
event.sender.send('fileData', data)
})
}
})
app.on('ready', createWindow)
Este código abrirá el cuadro de diálogo de apertura cada vez que nuestro proceso principal reciba un mensaje 'openFile' de un proceso de renderizado. Anteriormente, este cuadro de diálogo aparecía cada vez que se ejecutaba la aplicación. Limitémoslo ahora para que se abra solo cuando presionamosCommandOrControl+O.
Ahora crea un nuevo index.html archivo con el siguiente contenido -
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>File read using system dialogs</title>
</head>
<body>
<p>Press CTRL/CMD + O to open a file. </p>
<script type = "text/javascript">
const {ipcRenderer, remote} = require('electron')
const {globalShortcut} = remote
globalShortcut.register('CommandOrControl+O', () => {
ipcRenderer.send('openFile', () => {
console.log("Event sent.");
})
ipcRenderer.on('fileData', (event, data) => {
document.write(data)
})
})
</script>
</body>
</html>
Registramos un nuevo atajo y pasamos una devolución de llamada que se ejecutará cada vez que presionemos este atajo. Podemos dar de baja los accesos directos cuando no los necesitemos.
Ahora, una vez que se abra la aplicación, obtendremos el mensaje para abrir el archivo usando el acceso directo que acabamos de definir.
Estos atajos se pueden personalizar permitiendo al usuario elegir sus propios atajos para acciones definidas.
Las variables de entorno controlan la configuración y el comportamiento de la aplicación sin cambiar el código. Ciertos comportamientos de Electron están controlados por variables de entorno porque se inicializan antes que los indicadores de la línea de comandos y el código de la aplicación.
Hay dos tipos de variables ambientales codificadas en electrones: Production variables y Development variables.
Variables de producción
Las siguientes variables de entorno están diseñadas para su uso en tiempo de ejecución en aplicaciones empaquetadas de Electron.
No Señor | Variable y descripción |
---|---|
1 | GOOGLE_API_KEY Electron incluye una clave API codificada para realizar solicitudes al servicio web de codificación geográfica de Google. Debido a que esta clave de API se incluye en todas las versiones de Electron, a menudo excede su cuota de uso. Para solucionar este problema, puede proporcionar su propia clave API de Google en el entorno. Coloque el siguiente código en su archivo de proceso principal, antes de abrir cualquier ventana del navegador que realice solicitudes de codificación geográfica: |
2 | ELECTRON_RUN_AS_NODE Inicia el proceso como un proceso normal de Node.js. |
3 | ELECTRON_FORCE_WINDOW_MENU_BAR (Linux Only) No use la barra de menú global en Linux. |
Variables de desarrollo
Las siguientes variables de entorno están destinadas principalmente a fines de desarrollo y depuración.
No Señor | Variable y descripción |
---|---|
1 | ELECTRON_ENABLE_LOGGING Imprime el registro interno de Chrome en la consola. |
2 | ELECTRON_ENABLE_STACK_DUMPING Imprime el seguimiento de la pila en la consola cuando Electron falla. |
3 | ELECTRON_DEFAULT_ERROR_MODE Muestra el cuadro de diálogo de bloqueo de Windows cuando Electron falla. |
Para establecer cualquiera de estas variables de entorno como verdadera, configúrelo en su consola. Por ejemplo, si desea habilitar el registro, utilice los siguientes comandos:
Para ventanas
> set ELECTRON_ENABLE_LOGGING=true
Para Linux
$ export ELECTRON_ENABLE_LOGGING=true
Tenga en cuenta que deberá configurar estas variables de entorno cada vez que reinicie su computadora. Si desea evitarlo, agregue estas líneas a su.bashrc archivos.
Tenemos dos procesos que ejecutan nuestra aplicación: el proceso principal y el proceso de renderizado.
Dado que el proceso de renderizado es el que se está ejecutando en la ventana de nuestro navegador, podemos usar las herramientas de desarrollo de Chrome para depurarlo. Para abrir DevTools, use el atajo "Ctrl + Shift + I" o la tecla <F12>. Puedes ver cómo usar devtools aquí .
Cuando abra DevTools, su aplicación se verá como se muestra en la siguiente captura de pantalla:
Depurar el proceso principal
DevTools en una ventana del navegador Electron solo puede depurar JavaScript que se ejecuta en esa ventana (es decir, las páginas web). Para depurar JavaScript que se ejecuta en el proceso principal, necesitará usar un depurador externo e iniciar Electron con el interruptor --debug o --debug-brk .
Electron escuchará los mensajes del protocolo del depurador V8 en el puerto especificado; un depurador externo deberá conectarse a este puerto. El puerto predeterminado es 5858.
Ejecute su aplicación usando lo siguiente:
$ electron --debug = 5858 ./main.js
Ahora necesitará un depurador que admita el protocolo de depuración V8. Puede utilizar VSCode o node-inspector para este propósito. Por ejemplo, sigamos estos pasos y configuremos VSCode para este propósito. Siga estos pasos para configurarlo:
Descargue e instale VSCode . Abra su proyecto Electron en VSCode.
Agregar un archivo .vscode/launch.json con la siguiente configuración -
{
"version": "1.0.0",
"configurations": [
{
"name": "Debug Main Process",
"type": "node",
"request": "launch",
"cwd": "${workspaceRoot}",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
"program": "${workspaceRoot}/main.js"
}
]
}
Note - Para Windows, use "${workspaceRoot}/node_modules/.bin/electron.cmd" para runtimeExecutable.
Establezca algunos puntos de interrupción en main.jsy comience a depurar en la vista de depuración. Cuando llegue a los puntos de interrupción, la pantalla se verá así:
El depurador VSCode es muy poderoso y lo ayudará a corregir errores rápidamente. También tienes otras opciones comonode-inspector para depurar aplicaciones electrónicas.
Empaquetar y distribuir aplicaciones es una parte integral del proceso de desarrollo de una aplicación de escritorio. Dado que Electron es un marco de desarrollo de aplicaciones de escritorio multiplataforma, el empaquetado y distribución de aplicaciones para todas las plataformas también debería ser una experiencia perfecta.
La comunidad de electrones ha creado un proyecto, empaquetador de electrones que se encarga de lo mismo por nosotros. Nos permite empaquetar y distribuir nuestra aplicación Electron con paquetes específicos del sistema operativo (.app, .exe, etc.) a través de JS o CLI.
Plataformas compatibles
Electron Packager se ejecuta en las siguientes plataformas de host:
- Windows (32/64 bits)
- OS X
- Linux (x86 / x86_64)
Genera ejecutables / paquetes para las siguientes plataformas de destino:
- Windows (también conocido como win32, tanto para 32/64 bits)
- OS X (también conocido como darwin) / Mac App Store (también conocido como mas)
- Linux (para arquitecturas x86, x86_64 y armv7l)
Instalación
Instale el empaquetador de electrones usando -
# for use in npm scripts
$ npm install electron-packager --save-dev
# for use from cli
$ npm install electron-packager -g
Aplicaciones de empaque
En esta sección, veremos cómo ejecutar el empaquetador desde la línea de comandos. La forma básica del comando es:
electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> [optional flags...]
Esta voluntad ...
Busque o descargue la versión correcta de Electron.
Utilice esa versión de Electron para crear una aplicación en <output-folder> / <appname> - <platform> - <arch>.
--platform y --archse puede omitir, en dos casos. Si especifica--allen su lugar, se crearán paquetes para todas las combinaciones válidas de plataformas / arquitecturas de destino. De lo contrario, se creará un solo paquete para la plataforma / arquitectura de host.
Hemos utilizado los siguientes recursos para obtener más información sobre Electron. Nos hemos referido a estos al crear este tutorial.
El recurso más importante es la documentación de Electron. La documentación tiene una amplia cobertura de casi todas las características y peculiaridades del marco. Están lo suficientemente solos como para abrirse camino en la creación de una aplicación.
También hay algunos ejemplos de electrones muy buenos presentados en el repositorio de aplicaciones de muestras de electrones.
Recursos de video
Aplicaciones de escritorio con idiomas web
Desarrollo rápido de aplicaciones de escritorio multiplataforma utilizando JavaScript y Electron
Publicaciones del blog
Construyendo una aplicación de escritorio con Electron
Construye un reproductor de música con React & Electron
Creando su primera aplicación de escritorio con HTML, JS y Electron
Cree aplicaciones de nodo de escritorio multiplataforma con Electron