John Cardozo
Software Engineer
John Cardozo
John Cardozo
Framework Open Source para desarrollo de aplicaciones multiplataforma
Motor de renderizado
Node.js
Chromium
Motor de ejecución
HTML
CSS
Javascript
Plataforma de Ejecución
Lenguaje de desarrollo
VS Code
Atom
Figma
Notion
Github Desktop
MongoDB Compass
Invision
Vivifyscrum
Insomnia
Postman
Wordpress
Teams
Facebook Messenger
Slack
Discord
Twitch
Desarrollo
Comunicación
Proyectos y CMS
Prototipado
Instalación
Verificación
node --version
npm --version
Node Package Manager
Node
Inicialización del proyecto
npm init -y
El flag -y contesta a todas las preguntas con "yes"
Instalación de Electron
npm i electron -D
Genera el folder node_modules
Si se está usando git se debe crear el archivo .gitignore que excluye el folder node_modules del repositorio de código
"devDependencies": {
"electron": "^12.0.6"
}
archivo package.json
{
"main": "src/main.js"
}
archivo de inicio de la app
{
"start": "electron ."
}
instrucción de ejecución
folder de librerías de Node.js
folder de código de la aplicación
folder de views = archivos html
archivo principal de interfaz
archivo principal de aplicación
archivo de exclusión de git
archivo de configuración del proyecto
package.json
// Librerías
const { app, BrowserWindow } = require("electron");
const url = require("url");
const path = require("path");
let ventanaPrincipal;
// Evento "ready" de la aplicación
app.on("ready", () => {
// Creación de la ventana principal
ventanaPrincipal = new BrowserWindow({});
// Carga del archivo index.html en la ventana
ventanaPrincipal.loadURL(
url.format({
pathname: path.join(__dirname, "views/index.html"),
protocol: "file",
slashes: true,
})
);
});
main.js
npm start
instrucción de ejecución
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Todo Manager</title>
</head>
<body>
<h1>Tareas</h1>
<ul>
<li>Tarea1</li>
<li>Tarea2</li>
<li>Tarea3</li>
</ul>
</body>
</html>
index.html
npm install electron-reload electron-reloader --save-dev
Instalación
// Electron reload en modo desarrollo
if (!app.isPackaged) {
require('electron-reload')(__dirname, {
electron: path.join(__dirname,
'node_modules', '.bin', 'electron'),
hardResetMethod: 'exit'
})
try {
require('electron-reloader')(module, {
debug: true,
watchRenderer: true
});
} catch (_) {
console.log('Error');
}
}
archivo principal: main.js
// Libreria
const { Menu } = require("electron");
app.on("ready", () => {
// ...
// Carga el menu de un template
const menuPrincipal =
Menu.buildFromTemplate(templateMenu);
Menu.setApplicationMenu(menuPrincipal);
});
Librería y carga en app.on('ready')
const templateMenu = [
{
label: "Tareas",
submenu: [
{
label: "Nueva",
accelerator: "Ctrl+N",
click() {
console.log("click");
},
},
],
},
];
Librería y carga en app.on('ready')
const templateMenu = [
// ...
];
// Verifica si el SO es Mac
if (process.platform === "darwin") {
// Elimina del menu la opción
// con el nombre de la app
templateMenu.unshift({
label: app.getName(),
});
}
Elimina el nombre de la app
Solo en Mac
let ventanaNuevaTarea;
function crearVentanaNuevaTarea() {
// Crea la ventana de una nueva tarea
ventanaNuevaTarea = new BrowserWindow({
width: 400,
height: 300,
title: "Nueva tarea",
});
// Elimina el menu por defecto. SOLO WINDOWS Y LINUX
ventanaNuevaTarea.setMenu(null);
// Carga del archivo "nuevaTarea.html"
ventanaNuevaTarea.loadURL(
url.format({
pathname: path.join(__dirname, "views/nuevaTarea.html"),
protocol: "file",
slashes: true,
})
);
}
Función que crea y muestra una nueva ventana
Se debe crear el archivo nuevaTarea.html
La función puede ser invocada desde el menú
app.on("ready", () => {
// ...
// Escucha el evento de cierre de la ventana principal
ventanaPrincipal.on("closed", () => {
// Cierra la aplicación
app.quit();
});
});
Al cerrar la ventana principal, la ventana nueva queda abierta
function crearVentanaNuevaTarea() {
// ...
// Escucha el evento de cierre de la ventana
ventanaNuevaTarea.on('closed', () => {
// Libera la memoria de la ventana
ventanaNuevaTarea = null;
})
}
Al cerrar la ventana, libera la memoria
const templateMenu = [
{
label: "Tareas",
submenu: [
{
label: "Nueva tarea",
accelerator: "Ctrl+N",
click() {
crearVentanaNuevaTarea();
},
},
{
label: "Salir",
accelerator: process.platform === 'darwin' ? "command+Q" : "Ctrl+Q",
click() {
app.quit();
},
},
],
},
];
Verifica el SO para ver cuál shortcut se debe asignar
// Verifica que la aplicación
// no esté empaquetada
if (!app.isPackaged) {
// Agrega una nueva opción al menú
templateMenu.push({
label: "DevTools",
submenu: [
{
label: "Mostrar/Ocultar Dev Tools",
click(item, focusedWindow) {
focusedWindow.toggleDevTools();
},
},
{
role: "reload",
},
],
});
}
Nueva opción del menú, sólo si la app no está empaquetada
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
Bootstrap
<link rel="stylesheet" href="https://bootswatch.com/4/lux/bootstrap.min.css">
Bootswatch
CSS en el proyecto
<link rel="stylesheet" href="../styles/estilo.css">
Photon
<div class="container p-4">
<h1>Nueva tarea</h1>
<form>
<div class="form-group">
<label for="tarea">Nombre de la tarea</label>
<input type="text" id="tarea"
class="form-control" autofocus>
</div>
<button id="boton"
class="btn btn-info btn-block">Crear tarea</button>
</form>
</div>
HTML
nuevaTarea.html
index.html
main.js
on
ipcMain
ipcRenderer
send
escucha eventos
envía eventos
1
2
<script>
document.addEventListener("DOMContentLoaded", () => {
const { ipcRenderer } = require('electron')
// Obtiene el boton
let boton = document.getElementById("boton");
boton.addEventListener("click", (evento) => {
// Previene el envio del formulario
evento.preventDefault();
// Obtiene el nombre de la tarea
let tarea = document.getElementById("tarea").value;
// Objeto a ser enviado
const datos = {
tarea: tarea
}
// Envio de los datos al proceso principal
ipcRenderer.send("nueva-tarea", datos)
})
});
</script>
nuevaTarea.html
ventanaNuevaTarea = new BrowserWindow({
width: 400,
height: 300,
title: "Nueva tarea",
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
main.js
const { ipcMain } = require("electron");
app.on("ready", () => {
// ...
// Escucha el evento "nueva-tarea"
ipcMain.on("nueva-tarea", (evento, datos) => {
// Envía los datos a index.html
ventanaPrincipal.webContents.send('nueva-tarea', datos);
// Cierra la ventana para crear la nueva tarea
ventanaNuevaTarea.close();
});
});
main.js
// Ejecución cuando el DOM está creado
document.addEventListener("DOMContentLoaded", () => {
const { ipcRenderer } = require("electron");
// Escucha el evento "nueva-tarea"
ipcRenderer.on("nueva-tarea", (evento, datos) => {
// Obtiene la lista de tareas
let tareas = document.getElementById("tareas");
// Crea un elemento
let nuevoElemento = document.createElement("li");
nuevoElemento.innerHTML = datos.tarea;
// Agrega el elemento a la lista
tareas.appendChild(nuevoElemento);
})
});
index.html <script>
<script>
require('./index-renderer.js')
</script>
<script src="./index-renderer.js" defer>
</script>
Importar con sintaxis Nodejs
Importar con sintaxis HTML
Generación de aplicación final para diferentes sistemas operativos
electron-packager
aplicación escrita en Electron
Instalación de electron y electron-packager como devDependencies
npm install electron-packager --save-dev
Adicionar el nombre del producto a package.json
{
"productName": "Administrador de Tareas",
"devDependencies": {
"electron": "^10.1.5",
"electron-packager": "^15.1.0"
}
}
Creación del ícono de la aplicación
Crear los archivos de ícono en el folder "assets"
/assets/icon.icns
/assets/icon.ico
/assets/icon.png
Se puede descargar una imagen png transparente y transformarla a otros formatos en sitios web online
i
Adición de script
Modificar el archivo package.json
"scripts": {
"start": "electron .",
"package-mac": "electron-packager . --overwrite --platform=darwin --arch=x64 --icon=assets/icon.icns --prune=true --out=release",
"package-win": "electron-packager . --overwrite --platform=win32 --arch=ia32 --icon=assets/icon.ico --prune=true --out=release",
"package-linux": "electron-packager . --overwrite --platform=linux --arch=x64 --icon=assets/icon.png --prune=true --out=release"
}
npm run package-mac
npm run package-win
npm run package-linux
Generación del paquete
Adicionar el folder release al archivo .gitignore
!
release/
johncardozo@gmail.com
By John Cardozo
Creación de proyecto, ejecución y carga de HTML, CSS, menús, shortcuts, DevTools, BrowserWindow, procesos: ipcMain y ipcRenderer, eventos (send, on) y packaging.