• Tutte
  • Portfolio
  • Sviluppo
  • Tecnologia
  • Sviluppo di Desktop Apps Cross Platform con Electron

    di Denis Torresan

    Dai creatori di Atom, un tool per lo sviluppo ed il packaging di desktop apps cross platform.

    Electron è un framework Open Source che permette lo sviluppo di app cross platform utilizzando il medesimo approccio di Apache Cordova, ovvero attraverso JavaScript, HTML, e CSS.

    Si tratta di un modulo Npm, quindi eredita tutte le API e le funzionalità di Node.js.

    Questo articolo non vuole essere esaustivo, ma introduttivo alla piattaforma, torneremo sicuramente più avanti con altri articoli per entrare nel dettaglio di aspetti specifici della piattaforma.

     

     

    Una breve introduzione

    Electron, è ormai considerato un package stabile, arrivato alla versione 1.3.9, dispone di molti plugin già pronti all’uso e realizzati specificamente per la piattaforma. Tuttavia, il vero potenziale di Electron è dato dal fatto che si può costruire una desktop app utilizzando qualsiasi libreria scritta in NodeJS, rendendolo di fatto uno strumento molto potente anche per interagire con il sistema operativo.

    C’è praticamente di tutto, dalle librerie HTTP per accedere a server remoti, alla possibilità di interfacciarsi con il file system. Per Windows, ad esempio è anche disponibile un modulo nativo che permette di creare la Tray Icon con i menu contestuali. Insomma è un framework che rivoluziona completamente il modo con cui si possono sviluppare applicazioni desktop, con il vantaggio di essere già automaticamente multipiattaforma.

    Altro grande vantaggio è la gestione nativa degli updates dell’applicazione (aggiornamento automatico dell’app, con download dal server) e la possibilità di implementare gli installer (sempre multipiattaforma).

    Se ancora non vi ho convinto, guardate solo alcuni dei progetti che sono stati realizzati con questo strumento!

    AtomSlackVisual Studio CodeNuclide

    Qui la lista completa

     

    Quick Start

    Per facilitare l’avvio di un nuovo progetto, Electron dispone di un Quick Start scaricabile da GitHub:

    https://github.com/electron/electron-quick-start

    Come vedrete anche nelle istruzioni, una applicazione Electron necessita di tre files:

    • package.json – Descrittore dell’app, il classico file di npm con la lista delle librerie e delle dipendenze.
    • main.js – Il “main” dell’applicazione, che avviato (via NodeJS) crea una istanza del browser in modo da renderizzare l’html. Questo è chiamato il main process.
    • index.html – La pagina HTML da renderizzare all’avvio. A web page to render. Questo è chiamato renderer process.

    Diamo uno sguardo più nel dettaglio al contenuto dei files:

    package.json:

    {
      "name": "electron-quick-start",
      "version": "1.0.0",
      "description": "A minimal Electron application",
      "main": "main.js",
      "scripts": {
        "start": "electron ."
      },
      "repository": "https://github.com/electron/electron-quick-start",
      "keywords": [
        "Electron",
        "quick",
        "start",
        "tutorial",
        "demo"
      ],
      "author": "GitHub",
      "license": "CC0-1.0",
      "devDependencies": {
        "electron": "^1.4.1"
      }
    }

    Si tratta del “classico” package.json che chiunque utilizzi npm e nodejs conosce ed utilizza. Contiene informazioni di base sull’applicazione che si sta realizzando, e soprattutto, nella parte delle dipendenze, sono richiamate le dipendenze da caricare, in questo caso, essendo una app base, c’è solamente electron.

    main.js:

    const electron = require('electron')
    // Module to control application life.
    const app = electron.app
    // Module to create native browser window.
    const BrowserWindow = electron.BrowserWindow
    
    const path = require('path')
    const url = require('url')
    
    // 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.
    let mainWindow
    
    function createWindow () {
      // Create the browser window.
      mainWindow = new BrowserWindow({width: 800, height: 600})
    
      // and load the index.html of the app.
      mainWindow.loadURL(url.format({
        pathname: path.join(__dirname, 'index.html'),
        protocol: 'file:',
        slashes: true
      }))
    
      // Open the DevTools.
      mainWindow.webContents.openDevTools()
    
      // 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
      })
    }
    
    // This method will be called when Electron has finished
    // initialization and is ready to create browser windows.
    // Some APIs can only be used after this event occurs.
    app.on('ready', createWindow)
    
    // 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()
      }
    })
    
    app.on('activate', function () {
      // On OS X it's common to re-create a window in the app when the
      // dock icon is clicked and there are no other windows open.
      if (mainWindow === null) {
        createWindow()
      }
    })
    
    // In this file you can include the rest of your app's specific main process
    // code. You can also put them in separate files and require them here.

    Questo è il file più interessante, in quanto tutto il codice qui contenuto servirà a definire il funzionamento dell’applicazione. Una cosa interessante è che si può dividere il codice in moduli su files diversi, per tenere ordinato il tutto, e richiamarli nel main per poterli utilizzare.

    L’oggetto base da caricare è electron che si importa attraverso la direttiva require().

    Tramite la variabile electron sono disponibili gli oggetti:

    • app: oggetto che rappresenta l’istanza dell’applicazione su cui innestare tutti gli eventi di apertura e chiusura, ad esempio, oltre che per gestire gli update. Si tratta cioè del thread principale, nonchè l’oggetto con cui agire a livello di sistema operativo, per aggiungere ad esempio il menu alla finestra di sistema.
    • BrowserWindow : è l’oggetto che rappresenta l’istanza del browser embedded in electron. Tramite questo oggetto è possibile interagire a livello di rendering a livello di browser.

    Come si può vedere alla riga 20 di main.js, viene caricato il file index.html, ovvero l’interfaccia vera e propria, rappresentata per questa demo dal seguente file.

    index.html:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    </head>
    <body>
    <h1>Hello World!</h1>
    <!-- All of the Node.js APIs are available in this renderer process. -->
    We are using Node.js <script>document.write(process.versions.node)</script>,
    Chromium <script>document.write(process.versions.chrome)</script>,
    and Electron <script>document.write(process.versions.electron)</script>.
    </body>
    
    <script>
    // You can also require other files to run in this process
    require('./renderer.js')
    </script>
    </html>

    All’interno di index.html è anche possibile caricare file JS esterni che vengono utilizzati a livello di interfaccia.

    Questo framework infatti ha un punto di forza molto interessante, gli skills dello sviluppatore non devono essere troppo eterogenee, rendendo di fatto un frontend developer in grado di sviluppare applicazioni desktop senza dover apprendere nuovi linguaggi.

    Infatti il linguaggio di ‘coding’, è JavaScript, sia che si tratti di aspetti legati al backend, sia per quanto riguarda aspetti di gestione dell’interfaccia e layout.

     

    Esecuzione del Quick Start

    Come pre requisiti, è necessario solamente aver installato Node.js (e GIT).

    A questo punto, lanciare i seguenti comandi per scaricare le dipendenze, compilare e lanciare l’app:

    git clone https://github.com/electron/electron-api-demos
    cd electron-api-demos
    npm install
    npm start

    Questo è il risultato, come si può notare, in assenza di una definizione specifica, viene comunque proposto un menu di default, che può comunque essere completamente customizzato all’interno di main.js.

    electron-quickstart-first-run

    Un secondo modo per poter eseguire le applicazioni è sempre da command line, ma attraverso il comado ‘electron’, che va precedentemente installato (via npm):

    npm install -g electron

    a questo punto, sempre da console, lanciare l’applicazione con:

    electron .

    e si aprirà la finestra allo stesso modo di ‘npm start’.

    Per ora è tutto, ritorneremo sicuramente più avanti su questo fantastico strumento di lavoro che ci ha permesso di realizzare il client Desktop per Meta Gestione Scuola.

     

    Leggi anche...