Creare applicazioni desktop in maniera efficace grazie ad Angular ed Electron

Oggi, le applicazioni web che utilizziamo quotidianamente sono state sviluppate utilizzando framework e tecnologie che permettono agli sviluppatori di essere efficienti e veloci.

Al contrario, sviluppare applicazioni desktop rimane piuttosto complicato e macchinoso.

Per sviluppare applicazioni desktop, infatti, non c’è un unico stack tecnologico a cui fare riferimento: sono diffusi decine di linguaggi di programmazione (Java, C++, Python, …) e decine di framework e librerie per la costruzione di interfacce grafiche (Qt, Gtk, Swing, JavaFX, …).

Spesso queste librerie, poi, possono essere anche molto complesse da utilizzare (come faccio un layout fluido?), hanno scarsa documentazione e pochi esempi di codice…. Senza considerare che alcune non sono nemmeno cross-platform!

Perchè sviluppare applicazioni desktop deve essere così complicato? Come sarebbe se potessimo, in qualche modo, utilizzare le tecnologie web per creare app desktop con la stessa facilità?

Per rispondere a queste domande nasce Electron: un framework per la creazione di applicazioni native con tecnologie web come JavaScript, HTML e CSS, sviluppato da GitHub.

Ogni applicazione Electron è compatibile con tutti i sistemi operativi (Mac, Windows e Linux) e si integra perfettamente con i rispettivi menu nativi e sistemi di notifiche.

Già parecchie aziende hanno capito il potenziale di Electron ed hanno iniziato a sfruttare questa tecnologia, le app Electron sono tantissime ed insospettabili: Whatsapp, Skype, Slack, l’editor di testo Atom, Microsoft Visual Studio Code solo per citarne alcune.

In questo articolo vedremo come impostare un’applicazione Electron da zero con l’ultima versione di Angular e come preparare la nostra app per la distribuzione.

Creare una classica applicazione Angular

Per prima cosa creiamo una nuova applicazione Angular utilizzando l’Angular CLI:

npm install -g @angular/cli
ng new angular-electron
cd angular-electron

 

Modificare il file index.html

La pagina index.html generata di default punta il base href a /, questo ci creerà problemi con Electron e va cambiato.
E’ sufficiente aggiungere un punto prima dello slash nel file src/index.html.

<base href="./">

 

Installare Electron

Procediamo ad installare Electron utilizzando npm.

npm install electron --save-dev

 

Creare il file main.js

Ora che abbiamo installato Electron come dipendenza di sviluppo, possiamo creare il file main.js che sarà l’entrypoint vero e proprio della nostra applicazione.

const {app, BrowserWindow} = require('electron');

// E' necessario mantenere un riferimento globale all'oggetto 
// della finestra principale dell'app
// altrimenti la finestra verrà chiusa automaticamente quando l'oggetto
// verrà eliminato dal garbage collector di Javascript
let mainWindow;

function createWindow () {
	
	// Crea la finestra
	mainWindow = new BrowserWindow({width: 800, height: 600});

	// e carica il file index.html presente nella directory 'dist'
	// prodotto dalla build di Angular
	mainWindow.loadFile(`file://${__dirname}/dist/angular-electron/index.html`);

	// Callback da invocare quando la finestra viene chiusa
	mainWindow.on('closed', function () {

		// L'oggetto finestra non ci servè più, dereferenziamolo
		mainWindow = null;

	});

}

// Crea la finestra quando Electron è pronto
app.on('ready', createWindow);

// Callback da invocare quando tutte le finestre sono chiuse
app.on('window-all-closed', function () {

	// In macOS è comune che le app rimangano attive 
	// fino a che l'utente non le chiude esplicitamente con Cmd + Q
	if (process.platform !== 'darwin') {

		app.quit();

	}

});

app.on('activate', function () {

	// In macOS è comune che la finestra di un applicazione venga ricreata
	// quando viene cliccata l'icona nel Dock e non ci sono altre finestre aperte
	if (mainWindow === null) {

		createWindow();

	}

});

 

Creare il comando di build ed esecuzione in modalità produzione

Aggiungiamo al file package.json alcuni comandi per fare la build e lanciare la nostra applicazione.

{
	"name": "angular-electron",
	"version": "0.0.0",
	"main": "main.js", // <-- Aggiungi questa riga
	"scripts": {
		"ng": "ng",
		"start": "ng serve",
		"build": "ng build",
		"test": "ng test",
		"lint": "ng lint",
		"e2e": "ng e2e",
		"electron-build": "ng build --prod && electron ." // <-- Aggiungi questa riga
	},

...

Ora, lanciare la build di Angular ed eseguire la nostra app sarà semplice come digitare

npm run electron-build

Se hai eseguito tutti i passi precedenti correttamente, dopo aver lanciato questo comando, dovresti vedere la finestra della nostra app con all’interno la pagina di test con il logo di Angular.

Ambiente di sviluppo con hot code reload e strumenti per sviluppatori di Chrome

La nostra app è già pronta per essere distribuita (vedi sezione seguente) e non necessita di altro per funzionare.

E’ utile, però, configurarla per lo sviluppo in modo tale che le modifiche al codice Angular vengano caricate immediatamente, senza dover rieffettuare build, in una finestra dell’app che terremo sempre aperta.

Per fare ciò, prevederemo la possibilità di lanciare la nostra app in modalità sviluppo, impostando una variabile d’ambiente ENV con il valore DEV.

La finestra dell’app, se ENV=DEV, punterà all’indirizzo localhost:4200, dove sarà in ascolto il server web di sviluppo di Angular lanciato con il comando ng serve .

Siccome ng serve prima di mettersi in ascolto su localhost:4200 effettua alcune operazioni preliminari, potrebbe non essere subito raggiungibile.
E’ per questo motivo che, prima di far puntare la finestra Electron a localhost:4200, ci assicuriamo che ng serve sia in ascolto, altrimenti attendiamo e ritentiamo successivamente.

Modificare il file main.js

Nel file main.js al posto di

mainWindow.loadFile(`file://${__dirname}/dist/angular-electron/index.html`);

andiamo ad inserire

if (process.env.ENV == 'DEV') {

	// Mi collego all'endpoint ogni retryInterval millisecondi
	// fino a che non ricevo correttamente la pagina
	const request = require('request');
	const devLoadUrl = function(url, retryInterval) {

		request(url, function (error, response, body) {

			if (!error && response.statusCode == 200) {

				// Carica la pagina in una finestra Electron
				win.loadURL(url);
				// Apri gli strumenti per sviluppatori
				win.webContents.openDevTools();

			} else {

				setTimeout(function() { devLoadUrl(url); }, retryInterval);

			}

		});

	};

	devLoadUrl('http://localhost:4200', 1000);

} else {

	// Se la variabile d'ambiente ENV non è settata a DEV
	// procedo a caricare il file index.html
	// prodotto dalla build di Angular
	win.loadURL(`file://${__dirname}/dist/angular-electron/index.html`);

}

 

Creare il comando per lanciare l’app in modalità sviluppo

Aggiungiamo al file package.json il comando per lanciare la nostra applicazione in modalità sviluppo.

{
	"name": "angular-electron",
	"version": "0.0.0",
	"main": "main.js",
	"scripts": {
		"ng": "ng",
		"start": "ng serve",
		"build": "ng build",
		"test": "ng test",
		"lint": "ng lint",
		"e2e": "ng e2e",
		"electron-start": "ENV=DEV electron . | ng serve", // <-- Aggiungi questa riga
		"electron-build": "ng build --prod && electron ."
	},

...

Ora, per lanciare l’applicazione in modalità sviluppo, sarà sufficiente lanciare

npm run electron-start

 

Preparare l’applicazione per la distribuzione

Quando avremo terminato la nostra app, arriverà il momento di condividerla con il mondo.
Grazie ad Electron, la creazione di pacchetti per i vari sistemi operativi sarà davvero semplice.

Installiamo il tool electron-packager con npm

npm install electron-packager -g

Per creare gli eseguibili della nostra app basterà lanciare electron-packager con il parametro platform opportuno.

Il tool electron-packager, oltre al parametro platform, ha molte altre configurazioni possibili, rimando alla documentazione ufficiale per il dettaglio.

Eseguibile macOS:

electron-packager . --platform=darwin

Eseguibile Linux:

electron-packager . --platform=linux

Eseguibile Windows:

electron-packager . --platform=win32

Per poter generare un eseguibile Windows utilizzando electron-packager da sistemi Linux o macOS è necessario avere installato WineHQ.

0 commenti

Lascia un Commento

Vuoi partecipare alla discussione?
Fornisci il tuo contributo!

Lascia un commento

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