Wednesday, August 19, 2015

Getting started with NW.js (a.k.a. node-webkit)

Recently, I discovered a very interesting project on GitHub: nw.js (previously known as node-webkit). As you can see from the README file in the repository, it is a runtime for desktop applications based on Chromium (the open source project which powers the popular Chrome browser by Google) and io.js (a fork of node.js, a Javascript platform originally designed for building server-side applications).
This platform makes possible to write desktop applications using Javascript, HTML, CSS and web technologies such as browser-side libraries and frameworks (like JQuery and AngularJS) and node modules (often designed to work on the server side of web applications), which can be used to access system resources such as the filesystem. Node modules can be called directly from the "browser" context using the require() function.
Nw.js also provides APIs to integrate the applications with the desktop, so you can add, for example, native menus or a tray icon. All the documentation is available in the wiki.

In my opinion, nw.js has mainly two big advantages: first of all, it allows developers to use powerful web frameworks on the desktop, making possible, for example, to build nice user interfaces with Bootstrap (maybe animated with animate.css) which can interact with the operating system. Secondly, nw.js is cross-platform, so the built applications can be easily deployed to the major desktop operating system (Windows, OSX and Linux distributions).

There is, however, a downside: the size of the "compiled" applications. Probably "compiling" isn't the correct term since as the wiki explains, the suggested method of deployment consists in zipping the applications files (such as Javascript, HTML, CSS, node modules, etc) and then merging the archive with the nw.js executable or distributing them together. This means that each application will include a full Chromium browser, which isn't exactly lightweight: I tried to package on Windows a very simple image viewer application I made to learn nw.js and I got an app.exe file of 59MB and the full application directory with all the DLLs of 98MB. The DLLs may be not all necessary to run the application (some of them are for GPU acceleration and other for media playback); I haven't tried to delete them, however 60MB for an application that is a little more than an hello world is, in my opinion, too heavy anyway.
A possible solution to this problem may be providing a user-friendly way to make a system-wide nw.js installation, like already happens with other runtimes such as Java; this way, an user would need to download and install the core nw.js files only once (and eventually re-download them when a new version is available) and then install only the JS/HTML/CSS/etc files for each application without having each app taking up so much space. Someone has suggested a similar approach here, but as you can see from the discussion it seems like people involved with the project isn't very interested in this way of deploying applications.

Apart from this problem I think nw.js is a great framework for building cross-platform desktop applications and I'm currently learning to use it. The first working app I built is a tool to view image files contained in a folder as thumbnails, details list or slideshow. Here is a screenshot on Windows:

You can download the source code here. To run the application you need the NPM package manager on your PATH (it's usually installed when you install node.js). Unzip the archive to a folder, then open a terminal/command prompt in that folder and run npm install. This will download all the application's dependencies (which are nw.js and some libraries, like Bootstrap, JQuery) to the node_modules subfolder: it will probably take some time since, as I already said, nw.js files are quite large. Wait for it to finish, then you can run npm start to launch the application.
Note: when I ran the application on Ubuntu, I needed to run sudo chmod 777 -R * to obtain the necessary permissions; you'll probably need to do the same if you want to try the application on Linux or OSX.
More information is available in the README file in the archive.