BLOG

Miércoles, 18 Octubre 2017 11:17

Electron – Un framework para desarrollo de aplicaciones de escritorio multiplataforma (Segunda Parte)

AnatolyFoto

Continuamos con la segunda parte del blog escrito por Anatoly, en esta sección veremos paso a paso como construir una aplicación utilizando Electron. Si te perdiste el primer artículo, lo puedes encontrar en el siguiente enlace: Primera Parte

Construyendo una verdadera aplicación con Electron

En nuestro anterior artículo, explicamos la parte teórica de Electron y realizamos un ejemplo base. Ahora, profundizaremos con el desarrollo de una aplicación. Aplicando los principios y características base que nos otorga este poderoso framework, nuestra aplicación de escritorio Cross-Platform, comprenderá un ejemplo con 2 ventanas, una como padre y una como hija, que se comunicarán mediante eventos y compartirán información. La temática de esta demo será de un task list manager, con algunas características:

  •  Presentación con 2 pantallas enlazadas.
  • Una pantalla modal y con propiedades de presentación.
  • Permitirá agregar tareas a una lista.
  • Posibilidad de eliminar tareas individuales.
  • Limpiar la lista de tareas.
  • Ambas ventanas enlazados por eventos  de suscripción y emisión.
  • Integraremos un menú de opciones con shortcut de teclado.
  • Estilizado de UI mediante un framework de CSS.
  • Icono multiplataforma.

Iniciando el desarrollo:

Empecemos definiendo nuestro ambiente y el stack de desarrollo que vamos a utilizar para esta pequeña aplicación.

Necesitaremos tener previamente:

  • NodeJS con instalado con NPM como gestor de dependencias
  • Opcional instalar Yarnpkg como gestor de dependencias y para correr los builds.
  • Editor de texto o un IDE compatible con javascript, en este ejemplo usaré VSCode.

Iniciamos entonces con la creación de nuestro proyecto. Para esto, creamos los archivos principales que requiere una aplicación con Electron El nombre del proyecto será “TSS.TASKLIST.ELECTRON”, y procederemos a seguir los siguientes pasos para crear los ítems al poryecto:

  1. Archivo package.json (donde se referencian propiedades, dependencias y scripts  para compilar del proyecto)
  2. Archivo main.js (nuestro archivo principal de Electron)
  3. Archivo index.html (que sea nuestro parent windows)
  4. Archivo task.html (que sera child window)
  5. Folder para los CSS personalizados, dentro de ella crearemos un archivo app.css
  6. Folder de Assets, donde incluiremos en este ejemplo los iconos para Windows, Mac OS, Linux

Como icono usaremos uno gratuito, del website IconArchive. Descargaremos las 3 versiones .PNG, .ICO y .ICNS y lo guardaremos en la carpeta Assets. Esto nos servirá para referenciarlo en nuestra aplicación. Adicionalmente, renombraremos los archivos como icon.[ico,icns,png] ordenados en carpetas y por ultimo sacaremos una copia de icon.ico y lo renombramos como favicon.ico, para que se muestre como icono de la aplicación en la barra de títulos.

Electron 1

Vista del Icono escogido para el proyecto desde el website IconArchive

 Enlace: http://www.iconarchive.com/show/flat-finance-icons-by-graphicloads/target-market-icon.html

Entonces nuestro Proyecto debe quedar ordenado tal como se muestra en la siguiente imagen:

Electron 2

Estructura del proyecto como debe estar organizado para este ejemplo.

Luego tenemos que agregar como dependencia global Electron a nuestra aplicación

Electron 3

Luego a nuestro archivo package.json, deberá quedar con este contenido para seguir con nuestro desarrollo.

Electron 4.11

Continuando con muestro trabajo comenzaremos a ingresar completar los demás archivos para continuar diseñando nuestra app de tareas, tal como sigue a continuación:

App.css, que tendrán los styles base.

Electron 5

Index.html, en el cual asociamos la hoja de estilos y agregamos una lista html <ul></ul>, donde dinámicamente agregaremos los ítems de las tareas desde la ventana child, que será task.html

Electron 6

Task.html, agregamos un form con los controles para ingresar las tareas y botón submit y un enlace que mostraremos después como un botón para cerrar la ventana.

Electron 7

La parte más importante estará en main.js ya que aquí está el código que es el motor de la aplicación Electron, es el que gobierna los procesos y envía eventos y mensajes a los objetos que se comportarán como renderers.

Aquí también definímos qué módulos a usar, así como las opciones principales del menu de la aplicación que hace las llamadas a las ventanas y su interacción, incluyendo los shortcuts del menú,  también los usos de las API’s, definición de las ventanas y las llamadas a los archivos html y ciertas características de cómo se comportaran las ventanas globalmente. Para ser más detallado en la explicación del código, se ha hecho comentarios para su entendimiento:

Electron 40

 Ahora nos toca probar cómo se comporta nuestra aplicación, con todo el código que hemos completado, entonces solo nos falta correr unos comandos para cargar las dependencias, correr la aplicación y el resultado de todo. Entonces escribimos en el terminal de línea de comandos:

Electron 8

 El resultado de la aplicación debe tener el funcionamiento base, donde las ventanas se llaman entre ellas y deben mostrarse como la siguiente imagen:

Electron 9

Resultado de la aplicación en Electron solo funcional de las llamadas entre ventanas.

Por ahora todo funciona como lo deseamos, pero falta implementar algunas funcionalidades, las cuales serían:

-Enviar la información de la tarea desde task.html como ventana modal renderizada hacia la ventana main, index.html, para esto implementaremos la comunicación entre ventanas mediante los eventos e intercambio de información, para esto utilizaremos los módulos ipcMain y ipcRenderer.

-Incrustar la información de la tarea como un ítem de lista html en <ul><li></li><ul>, en index.html como ventana principal.

-Para eliminar una tarea de la lista, debemos implementar el eventListener al evento de doble click del mouse sobre el ítem, para removerlo de la lista html <ul><ul>

-Incluir los estilos y colores para la UI y los iconos para que se muestren en taskbar para todas las plataformas.

-Por último usar una herramienta de Electron para crear las paquetes distribuibles para cada plataforma, incluiremos los script commands en el archivo package.json.

Entonces empecemos a completar el código para nuestra aplicación, iniciaremos por complementar nuestro archivo principal main.js, para declarar nuestra instancia de escucha de Main Process. Para ello instanciaremos el módulo ipcMain, para un mejor entendimiento. La porción de código esta comentada para explicar al detalle de la implementación. Observar el código a continuación:

Electron 10.11

Luego implementaremos nuestros Renderer Process, instanciando el módulo de la API de Electron ipcRenderer para la recepción y envío de eventos y mensajes, para incrustar con html <li>, los ítems de tareas, así como también la limpieza de tareas y la captura del evento del doble click con la función para eliminar un ítem de la lista de tareas. Así que, creamos en index.html una sección de <script></script> al final de tag <body> que se comporta como nuestra ventana padre. Para un mejor detalle se incluye en forma de comentario cierta explicación del código, tal como se muestra a continuación:

Electron 30

Por lo que el código completo de nuestro archivo main.js el cual se comporta como nuestro MainProcess:

 

También incluiremos código en el html que será nuestra ventana hija task.html, una sección de <script></script> al final de tag <body>, que tendrá implementado envío de eventos y mensajes como parte del Render Process, instanciando también el módulo de la API de Electron ipcRenderer, que enviará los datos a la ventana padre y se cerrará simultáneamente al hacer click en el botón ‘Agregar’. Para más detalles se incluye la explicación con comentarios en el código:

 

Electron 11.11

 Aprovechamos también en agregar la acción del menú para limpiar todas las tareas de la lista enviando el evento. El código quedaría así:

Electron 12.1

Bueno, hasta ahora se ha completado parte del código que le da la funcionalidad requerida de nuestra aplicación. Solo nos queda probar y ver si todo correo como lo deseamos. Entonces nuevamente corremos la aplicación desde nuestro terminal de líneas de comandos.

Electron 13

El resultado hasta ahora debe tener funcionalidad. Podemos ayudarnos de los Dev Tools ante cualquier error. En caso contrario nuestra app queda lista para comenzar a darle acabo de styles y colores. A continuación, se muestra una imagen que es el resultado funcional de nuestra aplicación en Electron.

Electron 15.1

Vista funcional de la aplicación, que nos permite agregar tareas y la transición de datos entre ventanas

Siguiendo con el desarrollo y faltando ya poco para terminar, vamos a darle los toques finales a nuestra aplicación. Le daremos color y estilos de texto y estilos a los botones. Como hemos decidido usar un framework de CSS,  en esta oportunidad usaremos Materialized (http://materializecss.com/), un proyecto de Google que hereda los principios de Material Design para todo lo relacionado a UI en aplicaciones web y que podemos aplicarlo en nuestras aplicaciones Electron.

Entonces agregaremos a nuestros archivos html, que serían nuestras ventanas o pantallas (en index.htm y task.html), las referencias de la hoja de estilos de Materialized y además la tipografía escogida. Para este caso usaremos Roboto para nuestras ventanas. Esto afectara algunos cambios nuestro CSS personalizado. Bueno estas serían las referencias:

Electron 15.1

Y nuestra hoja de estilos CSS para nuestra aplicación quedaría así:

Luego de elegir las clases de estilos de Materialized que usaremos para la presentación de las pantallas y ventanas renderers de nuestra aplicación, debemos asignarlas en los archivos index.html y task.html, a los cuales le hemos agregados los tag html CSS class quedarían así:

Una vez terminado volvemos a correr la aplicación. El resultado de nuestra aplicación y su acabado de la UI, es tal cual se muestra en las secuencias de imágenes:

Electron 18    Electron 19

Resultado después de aplicar los Styles de Materialized y podemos ver los elementos con DevTool.

Por último, nos enmarcaremos en configurar la construcción de los paquetes o bundles de distribución para todas las plataformas. Lo que vamos a hacer es agregar la algunos build tasks en nuestros archivo package.json. Pero antes debemos agregar algunas dependencias de Electron que están ya maduras en el ecosistema para estos tipos de tareas, por lo que procedemos a agregarlos a nuestro entorno de desarrollo y serían las dependencias tal como se muestra a continuación:

 Electron 20.11

Nuestro archivo package.json, tendrá las referencias a las dependencias pero también agregaremos los build task para crear los distribuibles multiplataforma, cuyos parámetros se definen en la sección scripts, donde indicamos todos lo requerido y el folder de salida donde se crearan y la referencia a los iconos para cada plataforma entre otras opciones, por lo que,  entonces nuestro package.json quedaría como se muestra a continuación:

Y listo. Ya tenemos todo lo que necesitamos para nuestra aplicación y hemos cumplido todos los requisitos de diseño, funcionalidad, presentación y la configuración de construcción de distribuibles. Sólo nos falta correr los comandos para construir los paquetes distribuibles, estos serían ejecutados de la siguiente forma: 

 Electron 22.1

El producto de ejecutar los comandos, sería los distribuibles colocados en la carpeta ‘dist’ dentro del mismo proyecto, cuyo resultado es tal cual se muestra en la imagen a continuación.

Electron 23

Ya para ir cerrando este artículo, el resultado de nuestra aplicación, ejecutado desde su paquete producido con electron-packager, corrió sin problemas logrando todo lo propuesto, como se demuestra en las imágenes a continuación, que se han capturado en los ambientes de MacOS y Windows.

 

Electron 24

Electron 25

Electron 26

Electron 27

Electron 28

Electron 29

Electron 30

Repositorio de código fuente de la demo: https://github.com/apkalexei/tss.tasklist.electron

Conclusiones:

En la actualidad, Electron es una buena opción para el desarrollo de aplicaciones de escritorio cross platform, con tecnologías web como base, se presenta como alternativa a las aplicaciones tradicionales, tan comparable y con resultados superiores, inclusive con el uso de las tecnologías tradicionales como .Net.

A pesar de todo, existe algo que aún no sabemos y esto esta relacionado al rendimiento. Quizás no logran estar al mismo nivel de las aplicaciones bien diseñadas desde su arquitectura, pero constituye una alternativa para desarrollos de aplicaciones de gestión de alcance específico y es una opción más para desarrollar aplicaciones con tecnologías web.

Teniendo como resultado una aplicación de escritorio, lograr un buen diseño inicial y adaptable en el tiempo, necesita de la aplicación de patrones de diseño y de arquitectura que aseguran escalabilidad y mantenimiento.