Applicazioni desktop su Windows 10 utilizzando NW.js

Applicazioni desktop ibride, multipiattaforma scritte in html, css e JavaScript su Windows 10? Ecco come muovere i primi passi utilizzando NW.js.

Sul sito ufficiale di NW possiamo leggere:

NW.js is based on Chromium and Node.js. It lets you call Node.js code and modules directly from browser and also use Web technologies in your app. Further, you can easily package a web application to a native application.

Ossia NW ci consente, tra le altre cose, di impacchettare un’applicazione web in un’applicazione nativa. Non è per niente robetta da scuola elementare! 🙂

Poiché su Windows 10 alcuni moduli Node.js scaricati tramite npm non sono compatibili con nw.js (se non dopo una ricompilazione), per scrivere applicazioni desktop con nw.js su Windows 10 è opportuno seguire esattamente la seguente procedura:

  1. Scaricare e Installare Node.js (https://nodejs.org/it/) – versione LTS (consigliata)
  2. Creare la cartella del progetto e tutte le sottocartelle
  3. Creare il file main.html
  4. Entrare nella cartella principale del nostro progetto e creare il file package.json tramite il comando npm init
  5. Su Windows 10, prima di installare i moduli tramite node-gyp o npm, sostituire il file \node_modules\node-gyp\src\win_delay_load_hook.cc che si trova dentro la cartella in cui abbiamo installato npm – tipicamente qualcosa del tipo nodejs\node_modules\npm\node_modules\node-gyp\src\ – con quello presente al seguente link: https://github.com/nwjs/nw.js/blob/nw18/tools/win_delay_load_hook.cc
  6. Dalla root della cartella del progetto, installare nw-SDK: npm install nw –nwjs_build_type=sdk –save-prod
  7. Dalla root della cartella del progetto, installare il builder phoenix: npm install nwjs-builder-phoenix –save-dev
  8. Aggiungere gli script utili al builder phoenix nel file package.json
  9. Lanciare il progetto.

Procediamo…
Scaricare e installare Node.js non dovrebbe creare problema alcuno, pertanto si assume sia stato eseguito.

Creare la cartella del progetto e tutte le sottocartelle

Decidere la struttura delle cartelle che conterranno i file del nostro progetto è molto importante ed è qualcosa di estremamente soggettivo. In questa sede si suggerisce la seguente struttura:

nomeDelProgetto/
├── src/
│ ├── app/
│ │ └── main.js
│ ├── assets/
│ │ └── icon.png
│ ├── styles/
│ │ └── common.css
│ ├── views/
│ | └── main.html
└── package.json

In breve, si crea una cartella (nomeDelProgetto) che conterrà tutti i file del nostro progetto.
All’interno di tale cartella si crea la sotto cartella src e il file package.json.
Nella cartella src si creano 4 sotto cartelle: app (in cui inseriremo i file javascript), assets (in cui inseriremo immagini e icone), styles (in cui inseriremo i fogli di stile) e views (in cui inseriremo la schermate in formato HTML della nostra applicazione).

Creiamo il file main.html

Ora è il momento di scrivere un primo file HTML in grado di essere eseguito come applicazione desktop. In questo caso scriviamo un banalissimo file HTML come il seguente:

<!DOCTYPE html>
<html lang="it">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Titolo della finestra</title>
</head>
<body>
    <h1>LA MIA APPLICAZIONE DESKTOP IN NW.JS</h1>
</body>
</html>

Ricordiamoci che il file main.html, in base alla struttura delle cartelle scelta e in base a quanto dichiareremo nel file package.json, deve trovarsi esattamente nella seguente posizione: nomeDelProgetto/src/views/main.html.

Creare il file package.json tramite il comando npm init

Apriamo il prompt dei comandi di Windows (oppure la PowerShell) e navighiamo fin dentro la cartella principale (root) del nostro progetto.
Nell’esempio che segue la cartella del progetto è stata denominata nw_00.
Digitiamo, quindi, il comando npm init e seguiamo quanto riportato nell’immagine che segue (da notare che alla richiesta dell’entry point è stato inserito il percorso del file main.html poc’anzi creato).

npm_init

A questo punto avremo creato il file package.json nella root del nostro progetto.
Prima di procedere non dimentichiamo di sostituire il file \node_modules\node-gyp\src\win_delay_load_hook.cc

Installiamo NW-SDK e Builder-Phoenix

Sempre tramite prompt dei comandi o PowerShell rechiamoci nella root del nostro progetto e installiamo, in sequenza, l’SDK di NW e il builder che utilizzeremo per testare e distribuire il nostro progetto.
Per installare l’SDK di NW digitiamo il seguente comando:

npm install nw --nwjs_build_type=sdk --save-prod

Invece per installare il builder Phoenix, digitiamo quanto segue:

npm install nwjs-builder-phoenix --save-dev

Aggiungiamo gli script al file package.json per il builder Phoenix

Apriamo con un editor di testo il file package.json. Dovrebbe essere molto simile a qualcosa del genere:

{
  "name": "nome_del_progetto",
  "version": "1.0.0",
  "description": "Qui inseriamo una breve descrizione del progetto",
  "main": "/src/views/main.html",
  "dependencies": {
    "nw": "^0.36.4"
  },
  "devDependencies": {
    "nwjs-builder-phoenix": "^1.15.0"
  },
  "scripts": {
    "test": "run --x86 --mirror https://dl.nwjs.io/ ."
  },
  "author": "Alessandro Stella",
  "license": "ISC"
}

Deve diventare, invece, come il seguente (cambiamenti dalla riga 12 in poi):

{
  "name": "nome_del_progetto",
  "version": "1.0.0",
  "description": "Qui inseriamo una breve descrizione del progetto",
  "main": "/src/views/main.html",
  "dependencies": {
    "nw": "^0.36.4"
  },
  "devDependencies": {
    "nwjs-builder-phoenix": "^1.15.0"
  },
  "build": {
      "nwVersion": "0.36.4",
      "win": {
          "companyName": "Alessandro Stella",
          "icon": "src/assets/alexlogo_256x256.ico"
      }
  },
  "scripts": {
      "test": "run --x86 --mirror https://dl.nwjs.io/ .", 
      "dist_win": "build --tasks win-x86,win-x64 --mirror https://dl.nwjs.io/ .",
      "dist_linux": "build --tasks linux-x86,linux-x64 --mirror https://dl.nwjs.io/ .",
      "dist_mac": "build --tasks mac-x64 --mirror https://dl.nwjs.io/ .",
      "start32": "run --x86 --mirror https://dl.nwjs.io/ .",
      "start64": "run --x64 --mirror https://dl.nwjs.io/ ."
  }
}

Come è facile intuire, il file package.json è un file fondamentale nella scrittura del nostro progetto. Esso infatti contiene meta informazioni sul nostro progetto senza le quali non è possibile né l’esecuzione né la distribuzione della nostra applicazione. In futuro sarà importante entrare in confidenza con tale file. Per adesso accontentiamoci di comprendere quanto scritto qui sopra.
La sezione “build” serve alla successiva sezione “scripts”.
La sezione “scripts” verrà utilizzata dal builder Phoenix per lanciare il nostro progetto su una sistema operativo a 32 bit (“start32”) oppure su uno a 64 bit (“start64”).
Inoltre il builder Phoenix utilizzerà “dist_win” per creare una cartella “dist” all’interno della quale inserirà i file da distribuire per utilizzare il nostro progetto su piattaforma Windows a 32 e 64 bit. Allo stesso modo utilizzerà “dist_linux” per creare i file da utilizzare per lanciare il progetto su piattaforma Linux.

Eseguiamo il progetto

Fatto tutto quanto sopra riportato, abbiamo finito.
Dalla root del progetto, tramite il prompt dei comandi o PowerSell, richiamiamo il comando npm run start64 per eseguire il codice scritto a 64 bit, oppure il comando npm run start32 per eseguire il codice scritto a 32 bit.
Se abbiamo fatto tutto bene, dopo qualche secondo comparirà una finestra come la seguente
nw_prima_finestra

Discussione

Funzionato?
Bene, ma non abbiamo fatto ancora niente 😀
Ad esempio: un’applicazione desktop deve quasi certamente memorizzare dati e informazioni in modo persistente da qualche parte. Come facciamo a leggere e scrivere su disco fisso? E come facciamo a utilizzare una base di dati? E le eventuali comunicazioni tra le finestre?
Si può fare tutto ma serve tempo e studio…
La prima cosa da fare è studiare le API di NW.js. Ad esempio, dal seguente link http://docs.nwjs.io/en/latest/References/App/ si può leggere la documentazione dell’oggetto App che NW utilizza per consentire di accedere a informazioni della nostra applicazione. Dallo stesso link, sul menù di sinistra, scorrendo verso il basso, si possono trovare tutti gli altri oggetti di NW e imparare ad utilizzarli 🙂
Non basta.
Servirà senz’altro una base di dati.
Quale?
Le possiamo utilizzare tutte?
In questa sede si consiglia IndexedDB, un progetto del W3C e quindi cosa buona e giusta. Inoltre ci sono molte guide online su come interfacciarsi con questo DB ad oggetti e noSQL.

Da osservare anche che i i moduli caricati da Node.js non funzionano nello stesso modo su tutte le piattaforme. Pertanto per essere sicuri che tutto funzioni correttamente è opportuno lanciare un

npm install package.json

su ogni piattaforma su cui si desidera distribuire la propria applicazione desktop.

Infine prima o poi sarà necessario distribuire la nostra applicazione. Ci sono diversi modi per eseguire questo task. In questa sede si consiglia di utilizzare nwjs-builder-phoenix (https://github.com/evshiron/nwjs-builder-phoenix) non solo perché ci piace di più, ma soprattutto perché lo consigliano gli autori di NW.js 😉
In linea generale è bene sapere che per distribuire la propria applicazione desktop è necessario distribuire in blocco i file presenti nella cartella dell’SDK (tranne nwjc, payload e chromedriver). Quindi è necessario copiare i file dell’SDK da qualche parte, magari in una cartella denominata dist all’interno del nostro progetto, e poi creare il pacchetto di distribuzione con tutto il contenuto della cartella (task che viene egregiamente eseguito da Phoenix).

Bene.
Abbiamo tutte le carte in regola per iniziare a studiare questo affascinante mondo.
Appena troverò il tempo, scriverò un altro articolo su come leggere e scrivere un file su disco e su come interfacciarsi con IndexedDB 😉
Intanto, se questo articolo ti è stato utile… allora potrebbe esserlo anche per qualcun altro. Quindi perché non lo condividi?

Hai letto questi articoli?

2 Commenti

  1. Luke

    Bell’articolo. Io utilizzo la controparte Electron ed ho scoperto NW.js per le sue caratteristiche di entry point differenti da Electron come ad esempio una pagina html (motivo della mia ricerca). Hai mai provato a sviluppare un’app con NW.js utilizzando quest’approccio?

    1. Alessandro Stella

      Ciao Luke,
      a me è capitato di dover scegliere una piattaforma proprio tra Electron e NW. Ho scelto NW per un motivo “banale”: è più semplice (o meglio, è più semplice per me).
      Per quanto riguarda la tua domanda, la risposta è affermativa. Ho utilizzato NW per un magazzino che vende frutta secca e verdura. In tale circostanza ho anche utilizzato per la prima volta indexedDB. Ho compilato il software su Windows 10 e su Ubuntu. Nessun problema. L’applicazione comunque è decisamente modesta: 800 righe di CSS, 400 di HTML, 2500 di JS (puro, nessuna libreria), integrando fontawesome.
      Tuttavia per me, che per anni ho programmato le applicazioni desktop utilizzando java, javaFX e SQLite (o LevelDB e simili), è un nuovo mondo a cui sono approdato non appena Oracle ha deciso di escludere JavaFX dalle distribuzioni ufficiali. Per adesso non posso pronunciare alcuna critica. Ma ho appena iniziato…

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *