Creación de su primera aplicación de escritorio con HTML, JS y Electron

Las aplicaciones web se vuelven cada vez más poderosas cada año, pero todavía hay espacio para aplicaciones de escritorio con acceso total al hardware de su computadora. Hoy puede crear aplicaciones de escritorio utilizando HTML, JS y Node.js ya familiares, luego empaquetarlas en un archivo ejecutable y distribuirlas en consecuencia en Windows, OS X y Linux.

Hay dos proyectos populares de código abierto que lo hacen posible. Estos son NW.js, que cubrimos hace unos meses, y el Electron más nuevo, que usaremos hoy (vea las diferencias entre ellos aquí). Vamos a reescribir la versión anterior de NW.js para usar Electron, para que puedas compararlos fácilmente.

Empezando con Electron

Las aplicaciones creadas con Electron son solo sitios web que se abren en un navegador web Chromium integrado. Además de las API HTML5 regulares, estos sitios web pueden usar el conjunto completo de módulos de Node.js y módulos especiales de Electron que brindan acceso al sistema operativo.

Por el bien de este tutorial, crearemos una aplicación simple que obtenga los artículos más recientes de Tutorialzine a través de nuestro feed RSS y los muestre en un carrusel atractivo. Todos los archivos necesarios para que la aplicación funcione están disponibles en un archivo que puede obtener desde Descargar cerca de la parte superior de la página.

Extraiga su contenido en un directorio de su elección. A juzgar por la estructura de archivos, nunca adivinaría que se trata de una aplicación de escritorio y no de un simple sitio web.

Echaremos un vistazo más de cerca a los archivos más interesantes y cómo funciona todo en un minuto, pero primero, probemos la aplicación.

Ejecución de la aplicación

Dado que una aplicación Electron es solo una aplicación elegante de Node.js, deberá tener instalado npm. Puedes aprender cómo hacerlo aquí, es bastante sencillo.

Una vez que tenga eso cubierto, abra un nuevo cmd o terminal en el directorio con los archivos extraídos y ejecute este comando:

npm install

Esto creará un node_modules carpeta que contiene todas las dependencias de Node.js necesarias para que la aplicación funcione. Todo debería estar listo ahora, en la misma terminal que antes ingrese lo siguiente:

npm start

La aplicación debería abrirse en su propia ventana. ¡Observe que tiene una barra de menú superior y todo!

Probablemente haya notado que iniciar la aplicación no es demasiado fácil de usar. Sin embargo, esta es solo la forma en que el desarrollador ejecuta una aplicación Electron. Cuando esté empaquetado para el público, se instalará como un programa normal y se abrirá como tal, simplemente haciendo doble clic en su icono.

Cómo se hace

Aquí, hablaremos sobre los archivos más esenciales en cualquier aplicación electrónica. Comencemos con package.json, que contiene información diversa sobre el proyecto, como la versión, las dependencias de npm y otras configuraciones importantes.

paquete.json

{
  "name": "electron-app",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "dependencies": {
    "pretty-bytes": "^2.0.1"
  },
  "devDependencies": {
    "electron-prebuilt": "^0.35.2"
  },
  "scripts": {
    "start": "electron main.js"
  },
  "author": "",
  "license": "ISC"
}

Si ha trabajado con node.js antes, ya sabe cómo funciona. Lo más importante a tener en cuenta aquí son los scripts propiedad, donde hemos definido el npm start comando, lo que nos permite ejecutar la aplicación como lo hicimos antes. Cuando lo llamamos, le pedimos a electron que ejecute main.js expediente. Este archivo JS contiene una breve secuencia de comandos que abre la ventana de la aplicación y define algunas opciones y controladores de eventos.

principal.js

var app = require('app');  // Module to control application life.
var BrowserWindow = require('browser-window');  // Module to create native browser window.

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
var mainWindow = null;

// Quit when all windows are closed.
app.on('window-all-closed', function() {
    // On OS X it is common for applications and their menu bar
    // to stay active until the user quits explicitly with Cmd + Q
    if (process.platform != 'darwin') {
        app.quit();
    }
});

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
    // Create the browser window.
    mainWindow = new BrowserWindow({width: 900, height: 600});

    // and load the index.html of the app.
    mainWindow.loadURL('file://' + __dirname + '/index.html');

    // Emitted when the window is closed.
    mainWindow.on('closed', function() {
        // Dereference the window object, usually you would store windows
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        mainWindow = null;
    });
});

Eche un vistazo a lo que hacemos en el método 'listo'. Primero definimos una ventana del navegador y establecemos su tamaño inicial. Luego, cargamos el index.html archivo en él, que funciona de manera similar a abrir un archivo HTML en su navegador.

Como verá, el archivo HTML en sí no es nada especial:un contenedor para el carrusel y un párrafo donde se muestran las estadísticas de CPU y RAM.

index.html

<!DOCTYPE html>
<html>
<head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Tutorialzine Electron Experiment</title>

    <link rel="stylesheet" href="./css/jquery.flipster.min.css">
    <link rel="stylesheet" href="./css/styles.css">

</head>
<body>

<div class="flipster">
    <ul>
    </ul>
</div>

<p class="stats"></p>

<!-->In Electron, this is the correct way to include jQuery<-->
<script>window.$ = window.jQuery = require('./js/jquery.min.js');</script>
<script src="./js/jquery.flipster.min.js"></script>
<script src="./js/script.js"></script>
</body>
</html>

El HTML también enlaza con las hojas de estilo necesarias, las bibliotecas JS y los scripts. Tenga en cuenta que jQuery está incluido de una manera extraña. Consulte este número para obtener más información al respecto.

Finalmente, aquí está el JavaScript real para la aplicación. En él accedemos al feed RSS de Tutorialzine, buscamos artículos recientes y los mostramos. Si intentamos hacer esto en un entorno de navegador, no funcionará, porque la fuente RSS se encuentra en un dominio diferente y está prohibido obtenerla. En Electron, sin embargo, esta limitación no se aplica y simplemente podemos obtener la información necesaria con una solicitud AJAX.

$(function(){

    // Display some statistics about this computer, using node's os module.

    var os = require('os');
    var prettyBytes = require('pretty-bytes');

    $('.stats').append('Number of cpu cores: <span>' + os.cpus().length + '</span>');
    $('.stats').append('Free memory: <span>' + prettyBytes(os.freemem())+ '</span>');

    // Electron's UI library. We will need it for later.

    var shell = require('shell');

    // Fetch the recent posts on Tutorialzine.

    var ul = $('.flipster ul');

    // The same-origin security policy doesn't apply to electron, so we can
    // send ajax request to other sites. Let's fetch Tutorialzine's rss feed:

    $.get('http://feeds.feedburner.com/Tutorialzine', function(response){

        var rss = $(response);

        // Find all articles in the RSS feed:

        rss.find('item').each(function(){
            var item = $(this);

            var content = item.find('encoded').html().split('</a></div>')[0]+'</a></div>';
            var urlRegex = /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?/g;

            // Fetch the first image of the article.
            var imageSource = content.match(urlRegex)[1];

            // Create a li item for every article, and append it to the unordered list.

            var li = $('<li><img /><a target="_blank"></a></li>');

            li.find('a')
                .attr('href', item.find('link').text())
                .text(item.find("title").text());

            li.find('img').attr('src', imageSource);

            li.appendTo(ul);

        });

        // Initialize the flipster plugin.

        $('.flipster').flipster({
            style: 'carousel'
        });

        // When an article is clicked, open the page in the system default browser.
        // Otherwise it would open it in the electron window which is not what we want.

        $('.flipster').on('click', 'a', function (e) {

            e.preventDefault();

            // Open URL with default browser.

            shell.openExternal(e.target.href);

        });

    });

});

Lo bueno del código anterior es que en un archivo usamos simultáneamente:

  • Bibliotecas de JavaScript:jQuery y jQuery Flipster para hacer el carrusel.
  • Módulos nativos de Electron:Shell que proporciona API para tareas relacionadas con el escritorio, en nuestro caso, abriendo una URL en el navegador web predeterminado.
  • Módulos Node.js:sistema operativo para acceder a la información de la memoria del sistema, Pretty Bytes para formatear.

¡Y con esto nuestra aplicación está lista!

Embalaje y Distribución

Hay otra cosa importante que hacer para que su aplicación esté lista para los usuarios finales. Debe empaquetarlo en un ejecutable que se pueda iniciar con un doble clic en las máquinas de los usuarios. Dado que las aplicaciones de Electron pueden funcionar en múltiples sistemas operativos y cada sistema operativo es diferente, es necesario que haya distribuciones separadas para Windows, para OS X y para Linux. Herramientas como este módulo npm son un buen lugar para comenzar:Electron Packager.

Tenga en cuenta que el paquete toma todos sus activos, todos los módulos necesarios de node.js, más un navegador WebKit minimizado y los coloca juntos en un único archivo ejecutable. Todas estas cosas se resumen y el resultado final es una aplicación que tiene un tamaño aproximado de 50 MB. Esto es mucho y no es práctico para una aplicación simple como nuestro ejemplo aquí, pero se vuelve irrelevante cuando trabajamos con aplicaciones grandes y complejas.

Conclusión

La única diferencia importante con NW.js que verá en nuestro ejemplo es que NW.js abre una página HTML directamente, mientras que Electron se inicia ejecutando un archivo JavaScript y crea una ventana de aplicación a través del código. La forma de Electron le brinda más control, ya que puede crear fácilmente aplicaciones de ventanas múltiples y organizar la comunicación entre ellas.

En general, Electron es una forma emocionante de crear aplicaciones web de escritorio utilizando tecnologías web. Esto es lo que debe leer a continuación:

  • Guía de inicio rápido de Electron
  • Documentación de Electron
  • Aplicaciones creadas con Electron