In this article I am going to discuss developing desktop apps using Node-Webkit. Now you might be wondering what on earth this is, but stay tuned as I discuss Node-webkit in not too much details.
Over the last few weeks I have been searching for an easy way to create desktop apps that can run on Windows, Mac and Linux.
Now as most developers will know it’s not that easy in mainstream languages such as C#, but it can be done.
After finding Node-Webkit, I realised how easy it can be to create cross platform desktop apps using my favourite web technologies, HTML5 and Javascript. Node webkit is an app runtime that combines the chromium browser with Node.js and this allows you to essentially write a Node.js web app with an embedded HTML5 front end, and you can even use WebGL for some advanced 3D graphics.
You can read more about how it works here https://github.com/nwjs/nw.js
To get started with node.js apps you will need to install the node.js engine from the download on their website http://nodejs.org/
Next up you can use the npm commands in order to download and install node.js modules as well as to install node-webkit, which we need for our app runtime. Use this command to download and install node-webkit’s app runtime.
1 npm install nodewebkit
After creating your node-webkit project according to the website you can start running your app.
In order to run your node-webkit app you just have to zip your content and save it with a .nw extention and run it with the nw runtime.
But wait…this is really difficult to develop apps if you have to zip the content each time you want to test it, luckily there is a node-webkit builder called nwbuild that not only allows you to run your app while testing, it also allows you to build app packages for all the platforms.
You can have a look at nwbuild here https://github.com/mllrsohn/node-webkit-builder
While developing you simply have to run nwbuild from the command line like so:
1 nwbuild -r path/to/your/younwapp/
For myself I have created a batch file that I just need to double click, this saves a lot of typing during development.
Databases
As with most apps, local or remote there is always a need to store data. Node-webkit provides a lot of opportunities for local databases such as MongoDB, IndexedDB, PouchDB, EJDB, etc. and you can find a list of all the most used ones here https://github.com/nwjs/nw.js/wiki/Save-persistent-data-in-app
For my app I have chosen to use a little lesser know database named NeDB (Node embedded database) that is based on MongoDB but without the bulkiness and all of the awesomeness. https://github.com/louischatriot/nedb
NeDB is fast, easy to use and allows in memory as well as persisted data storage to file for your cross platform app. I chose NeDB purely for it’s simplicity and it doesn’t feel bulky or bloated.
Installing NeDB is quick using the npm command:
1 npm install nedb --save
The documentation for NeDB is very thorough and allows you to get started quickly. One thing that I did notice is that it runs async using callbacks, which I didn’t really like in my app, and wanted to wrap my DB logic in such a way that I can keep my code clean.
In order to get around this I used JavaScript promises to wrap my DB functions. Node.js has a cool library for promises called Q, yep just Q.
1 npm install q --save
After installing q you can wrap any function in a promise so that it can be called async, while still keeping your code clean. Promises works very much the same way as Tasks in C# by calling a method and using .then() to wait for it to finish.
For my example I used it to wrap a call to a settings database. The call on the database side will look something like this:
1 function _FindByKey(key) { 2 var deferred = App.Q.defer(); 3 4 App.settingsDB.findOne({ key: key }, function (err, doc) { 5 deferred.resolve(doc); 6 }); 7 8 return deferred.promise; 9 }
Wrapping a function with promises eliminates the need for the _FindByKey function to accept a callback, and you can call the function like this:
1 App.Settings.FindByKey("SomeSettingKey").then(function (setting) { 2 var value = setting.ObjectValue; 3 4 //Work with the setting 5 });
Database Encryption
NeDB is great, but the one thing it lacks is native support for database encryption. Encrypting your local database is very important, it helps to prevent anyone from discovering your database structure as well as to keep user data safe.
NeDB exposes two constructor methods or hooks, that we can use for encryption, they are called afterSerialization and beforeDeserialization. These two hooks allows us to transform the data after it was read from the database and before it is written to file.
In order to encrypt our data we need the crypto-js module that allows us to do AES encryption/decryption in node.js
Install crypto-js using the npm command and save it to your project:
1 npm install crypto-js --save
Now that we have a library to encrypt and decrypt our data with, we can hook into the two NeDB methods and transform our data.
Firstly to encrypt our data we can use a method such as this:
1 App.EncryptDB = function (strData) { 2 if (strData != undefined && strData != "") { 3 var encrypted = App.Crypto.AES.encrypt(strData, App.Constants.DBKey); 4 var ciphertext = encrypted.toString(); 5 6 return ciphertext; 7 } 8 else { 9 return strData; 10 } 11 }
And now to decrypt our data we simply have to do the reverse of the encrypt:
1 App.DecryptDB = function (strData) { 2 if (strData != undefined && strData != "") { 3 var decrypted = App.Crypto.AES.decrypt(strData, App.Constants.DBKey); 4 var plaintext = decrypted.toString(App.Crypto.enc.Utf8); 5 6 return plaintext; 7 } 8 else { 9 return strData; 10 } 11 }
And that’s it, cross platform app development using node-webkit with a local database.
There isn’t much more to it, except for the front end. It’s really easy and quick to get your app up and running.
Here are all the libraries I have used this far in my app…
Front-End:
- Jquery –Used for general DOM manipulation.
- Bootstrap –Used to style our app and get it responsive and looking great on all screen sizes.
- Knockout –Two way binding, it’s awesome, and saves you a lot of trouble.
Node-JS:
- nw.gui –Used for node-webkit container manipulation.
- Q –JavaScript promises for async functions.
- path –Used to work with file system paths in node.
- fs –Allows you to work with files and file streams.
- crypto-js –Used to encrypt the database and password hashing.
- moment –Formats our dates so that they are human readable.
- nedb –Our database store.
Should you have any comment or need help with node-webkit, feel free to leave me a comment and I’ll reply to you as soon as I can.