Cross-Plattform-Desktop-Entwicklung mit Angular und NW.js
Desktopentwicklung ist von vielen totgesagt aber dennoch allgegenwärtig. Doch wie sollte die Desktopentwicklung im Jahre 2015 oder 2016 aussehen? Vorbei sind die Tage, in denen man es sich als Softwareentwickler erlauben konnte, nur eine der drei großen Plattformen (Windows, OS-X und Linux) zu adressieren. Dieser Artikel bietet einen Einstieg in die Cross-Plattform-Desktop-Entwicklung auf Basis von HTML, JavaScript und CSS. Darüber hinaus werden Sie NW.js kennenlernen, welches Ihre HTML-App auf den oben genannten Plattformen als native App bereitstellt.
JavaScript ist überall! Im Web und auf dem Server ist die dynamische Skriptsprache nicht mehr wegzudenken. Es mag immer noch einige Entwickler geben, die sich davon abwenden. Doch spätestens, wenn diese sich mit der grenzenlosen Flexibilität und Fülle an Möglichkeiten ernsthaft beschäftigen, werden die Tage des JavaScript-Bashings endgültig gezählt sein. Im Bereich Webentwicklung verdankt JavaScript seinen Siegeszug Frameworks wie dem serverseitigen Node.JS oder auch Google’s AngularJS. Gerade in den letzten Jahren haben diese beiden Frameworks dafür gesorgt, dass immer mehr Entwickler und auch große Konzerne Ihre Liebe zu der Sprache neu entdeckt haben. Doch neben der klassischen Verwendung im Web und dem Einsatz auf dem Server fehlte immer noch die Möglichkeit, JavaScript sinnvoll auf dem Desktop einzusetzen.
Diese Lücke erkannten einige JavaScript-Community-Mitglieder und starteten in Zusammenarbeit mit dem Intel Open Source Technology Center das Projekt NW.js [1] – welches initial unter dem Namen node-webkit bekannt wurde.
NW.js ist ein "Framework" für die Erstellung von plattformübergreifenden Desktopanwendungen. Es bietet Support für die beliebten Plattformen OS-X, Linux und Windows an. Entgegen vielen anderen Ansätzen benötigt man als Entwickler allerdings keine Kenntnisse von klassischen Desktop-Programmiersprachen wie etwa C++ oder Java. NW.js stellt eine definierte Umgebung bereit, innerhalb der man als Entwickler HTML5-Anwendungen ausführen kann. Darüber hinaus kann jedes vorhandene Node.JS-Modul eingebunden und direkt innerhalb der HTML5-Anwendung verwendet werden.
Damit diese Verbindung stabil realisiert und auch im produktiven Einsatz robust verwendet werden kann, hat das NW.js-Team auf etablierte Standards gesetzt. Den gesamten Frontend-Teil übernimmt Chromium – die Open Source-Basis von Google Chrome – welche eine feste, integrierte Komponente frei von Abhängigkeiten zu externen Anwendungen darstellt. Um Node.JS-Module ausführbar zu machen, wird aktuell noch io.js [2] als zweite Kernkomponente mit jeder NW.js-Anwendung ausgeliefert. io.js und Node.JS haben sich mittlerweile wieder in Version 4.0.0 miteinander vereint, NW.js wird daher im kommenden Release den Support für Node.JS 4 einführen, was allerdings keinerlei Auswirkungen auf den Entwicklungsprozess als solchen haben wird.
Ihre erste Cross-Plattform-Desktop-Anwendung
Damit Sie die nachfolgenden Schritte selbst durchführen können, benötigen Sie eine funktionierende Node.JS-Installation auf Ihrem Computer. Sollten Sie noch keine Node.JS-Installation haben, installieren Sie einfach das offizielle Release von Node.JS auf Ihrem System [3].
Als Beispiel soll x-note – eine einfache kleine App zum Erfassen von Notizen – dienen, um aufzuzeigen, wie eine existierende HTML5-Anwendung nativ auf allen drei Plattformen bereitgestellt werden kann. Den Quellcode der x-note-Anwendung können Sie einfach auf github unter [4] herunterladen. Die App wurde unter Verwendung von AngularJS [5] und Angular-Material [6] entwickelt. Sie kann sowohl im Browser, als mobile App oder – wie in diesem Fall – als Desktop-Anwendung verwendet werden. Die für NW.js wichtigen Punkte im Quellcode werden wir im weiteren Verlauf des Artikels aufzeigen. Machen Sie sich also keine Sorgen, wenn Sie jetzt einige Teilbereiche des Quellcodes nicht zuordnen können.
Nachdem Sie das Projekt heruntergeladen haben, sollten Sie die nötigen Abhängigkeiten des Projekts installieren. Wechseln Sie hierzu in die Kommandozeile und navigieren Sie in das Projektverzeichnis und führen die folgenden Befehle aus.
$ npm install $ npm install bower gulp live-server –g $ bower install $ gulp build:web
Sie können sich die Anwendung bereits jetzt im Browser anschauen und sich damit vertraut machen. Führen Sie hierzu live-server dist im Projektverzeichnis aus. Ihr Standardbrowser sollte sich automatisch öffnen und Ihnen die Anwendung präsentieren.
Um die existierende Anwendung nun als Desktop-Anwendung ausführen zu können, sind zwei weitere Schritte notwendig: Zunächst benötigen Sie die ausführbaren Dateien von NW.js. Diese können ebenfalls einfach mittels npm installiert werden.
$ npm install nw –g
Die zweite Aufgabe besteht darin, die Desktop-Anwendung zu konfigurieren, hierzu wird ein Manifest für unsere Desktop-Anwendung benötigt. Das Manifest für NW.js-Anwendungen ist ein JSON-Objekt, welches immer als Datei mit dem Namen package.json im Anwendungsverzeichnis existieren muss. Parallel zur Ausführung um Web wird auch die Desktop-Variante von x-note auf Basis der fertig kompilierten Anwendung ausgeführt. Daher benötigen wir eine package.json im Unterordner dist.
In der minimalsten Form muss das Manifest die Eigenschaften name, version und main beinhalten. Lediglich die letztere der Eigenschaften bedarf einer kurzen Betrachtung. Als main muss die initiale HTML-Seite angegeben werden, welche geladen werden soll, sobald die Anwendung gestartet wird. Auch wenn in unserem Beispiel die Datei index.html einen standardisierten Namen hat, für NW.js muss dieser explizit angegeben werden. Daraus ergibt sich eine initiale package.json-Datei mit dem folgenden Inhalt.
{ “name”: “x-note”, “version”: “1.0.0”, “main”: “index.html” }
Anstatt die Datei unter dem Namen package.json zu speichern, legen Sie diese im Unterordner src mit dem Namen app.package.json ab, um nicht unnötig mit der projektweiten package.json in Konflikt zu geraten.
Nachdem Sie die Anpassungen vorgenommen haben, können Sie die Anwendung erneut kompilieren. Verwenden Sie diesmal allerdings einen weiteren Build-Task, welcher für das Kopieren und Umbenennen des Manifestes verantwortlich ist.
$ gulp build $ gulp private:app:package
Somit sollten alle benötigten Artefakte im dist-Ordner vorhanden sein und sie können die Anwendung auf Ihrem PC testen, indem Sie nw dist im Projektverzeichnis ausführen. Die Anwendung sollte sich wie in Abb.1 auf Ihrem System präsentieren.
Im Gegensatz zur Webversion werden ihre Notizen jetzt allerdings auf der Festplatte gespeichert, hierfür ist der FileSystemService verantwortlich. Durch eine einfache Überprüfung, ob die aktuelle Anwendung in NW.js ausgeführt wird oder in einem normalen Browser, wird an dieser Stelle entschieden, welche Variante des FileSystemService verwendet wird (s. Listing 1). Sofern die Anwendung im Kontext von NW.js ausgeführt wird, werden Ihre Notizen ins Dateisystem geschrieben und sind somit über einen Anwendungsstart hinweg verfügbar. Hierzu werden lediglich Standard-Node.JS-Module verwendet, welche den Dateisystemzugriff für sämtliche Plattformen abstrahieren und dem Entwickler eine einfache JavaScript-API zur Verwendung anbieten.
Listing 1: FileSystemService
function DesktopFileSystemService(){
var fs = require('fs'),
gui = require('nw.gui'),
path = require('path');
this.save = function(notes){
var fileDescriptor = fs.openSync(path.join(gui.App.dataPath, "data.json"), "w+");
fs.writeSync(fileDescriptor, JSON.stringify(notes));
};
this.load = function(){
var fullPath = path.join(gui.App.dataPath, "data.json");
var data = [];
try{
data = JSON.parse(fs.readFileSync(fullPath));
}catch (error){
// data file not present
}
return data;
};
}
function WebFileSystemService($window){
this.save = function(notes){
$window.localStorage.setItem('xnotes::allNotes', JSON.stringify(notes));
};
this.load = function(){
var storageValue = $window.localStorage.getItem('xnotes::allNotes');
if(!storageValue) {
return [];
}
return JSON.parse(storageValue);
};
}
WebFileSystemService.$inject = ['$window'];
function FileSystemServiceFactory($injector, runtimeService){
if(runtimeService.isNwJsApp()){
return $injector.instantiate(DesktopFileSystemService);
}else{
return $injector.instantiate(WebFileSystemService);
}
}
angular.module('xnote').factory('fileSystemService', FileSystemServiceFactory);
Automatisierung der Buildaufgaben
An dieser Stelle haben Sie die Anwendung bereits erfolgreich auf Ihrem Desktop ausgeführt. Doch nun gilt es den Erstellungsprozess zu realisieren, so dass automatisch ausführbare Dateien für die jeweiligen Plattformen erstellt werden. In unserer Beispielanwendung wird GulpJS für die Build-Automatisierung eingesetzt. In Verbindung mit dem Open Source-Modul nw-builder kann genau diese Aufgabe automatisiert werden, so dass nach dem Aufruf von
$ gulp build:desktop
die x-note-Anwendung für Windows, Linux und OS-X als ausführbare Anwendung generiert werden kann. Den entsprechenden Code zur Konfiguration des Build-Prozesses finden Sie in Listing 2. Hierbei handelt es sich lediglich um einen Auszug der Datei gulptasks/desktop.js aus dem Projektverzeichnis.
Listing 2: Build-Automatisierung mit GulpJS
gulp.task('private:build:nw', function(done) {
var homeDir = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
var nw = new tasks.NwBuilder({
files: 'dist/**/*',
cacheDir: tasks.path.join(homeDir, '.cache'),
buildDir: tasks.path.join(process.cwd(), "desktop-build"),
version: '0.12.3',
platforms: ['win32', 'win64', 'osx64', 'linux32', 'linux64'],
macIcns: 'assets/x-note.icns',
winIco: 'assets/x-note.ico',
macZip: false
// uncomment the previous row if you're buiding the app on windows or if you've followed this guide
// https://github.com/nwjs/nw.js/wiki/Icons
});
nw.build();
done();
});
Neben der expliziten Angabe der gewünschten Plattformen und den Dateien, die in unsere App fließen sollen, werden noch weitere optionale Parameter an den nw-builder übergeben. Eine komplette Liste aller verfügbaren Parameter finden Sie unter [7].
Wie Sie sehen ist auch die Automatisierung von NW.js dank existierender Open Source-Komponenten und Frameworks, welche einfach geschickt kombiniert wurden, einfach realisierbar. Abschließend möchte ich noch eine Alternative erwähnen, denn wie immer macht es hier Sinn, sich den gesamten Markt anzuschauen.
Electron – Die junge Alternative
NW.js hat keine Monopolstellung mehr auf dem Markt der Cross-Plattform-Desktopentwicklungen. Das Unternehmen github bietet mit Electron eine gute Alternative an. Electron bietet Ihnen die gleichen Möglichkeiten, allerdings auf einer etwas anderen Architektur. Im Gegensatz zu NW.js trennt Electron die Ausführung der HTML5-Anwendung und der Node.JS-Programmteile in einzelne Unterprozesse auf. Als Entwickler werden Sie sich daher auch mit Themen wie Inter-Process-Communication (kurz IPC) oder Remote-Code-Execution auseinandersetzen müssen, um direkt aus der HTML5-Anwendung heraus Node.JS-Code ausführen zu können. Im direkten Vergleich wird NW.js oftmals aus zwei Gründen bevorzugt. Zum einen ist NW.js die ausgereiftere Plattform, hier sind viele Themen wie zum Beispiel die NTLM-Authentifizierung bereits integriert. Zum anderen gibt es bereits sehr viele NW.js-Anwendungen auf dem Markt. Dadurch gibt es bereits viele Erfahrungsberichte und Anleitungen, wie man NW.js-basierte Anwendungen in den jeweiligen App-Stores verfügbar macht. Dennoch sollten Sie auch etwas Zeit in Electron investieren, denn im Endeffekt kommt es immer auf die konkrete Anforderung an, welche Sie gerade meistern müssen.
Hinweis
Falls dieses Thema Ihr Interesse geweckt hat, sollten Sie sich unbedingt das aktuelle Entwickler-Sonderheft zum Thema Cross-Plattform-Entwicklung kaufen, dort wird auch das Thema Cross-Plattform-Desktopanwendungen mit NW.js detailliert behandelt. Sie können das Sonderheft entweder am Kiosk oder online unter [8] kaufen.
- Github: nw.js
- io.js 3.3.1 (Download)
- Nodejs.org (Download)
- Github: ThorstenHans / x-note
- Angularjs
- Angularjs: Material
- Github: nw-builder
- Entwickler: Shop