Build Desktop Apps with JavaScript and Node WebKit

by Ben Farrell on February 10, 2014

The modern web is always changing, and this article is more than two years old.

By Ben Farrell

I’m a big fan of platforms that enable me to experiment and do creative things. As someone who was big into Flash and tends to do mostly HTML/JS/CSS now, the main problem with both of these is that they are limited by the capability of the browser. If the browser allowed me to do everything I wanted, we’d have a lot of unhappy and insecure browser users. I’m talking about things like access to the user’s file system, running random bits of C++, et cetera. Basically, lots of the ideas I have that would be super cool to do are also things that malicious developers would love to do to compromise your machine.

While current browsers are occasionally limiting, the languages and underlying tech we use in browsers are not. There is a long history of various wrappers that take a web app and give it extra capability as a desktop application. These wrappers will often remove many of the restrictions imposed by browsers and allow us to do virtually anything we as developers might want to do.

What if we could approach the problem from a different angle? What if we took an existing, non-visual platform that already allows developers to do whatever they want and put a visual layer on top of it? That platform is Node.js and that visual layer is WebKit. Put them together, with Javascript as the underlying engine and WebKit as the visual layer, and you have Node-WebKit!

Node-WebKit is created and developed in the Intel Open Technology Center. It has a couple years’ worth of maturity under its belt as well. In this post I’ll show you how to get started with Node-Webkit and even build your first application.

Why Node.js?

Maybe you like Ruby, Python, or another awesome language that offers the capabilities that I’m talking about. These platforms are great (I’ve done some Python and love it), but Node.js offers us something that the others don’t have: Javascript.

Javascript is, of course, common to working with Node.js and WebKit, and that is its biggest positive in this case. We can write Javascript for Node.js or WebKit with little regard for where Node ends and the visual layer begins. We can mix in Node.js specific file-system calls in the middle of our jQuery UI component or AngularJS directive.

Application development feels extremely cohesive with Node WebKit. Additionally, because Javascript is the most popular language today due to its ubiquitous web presence, we have a massive number of UI toolkits and frameworks to choose from.

Getting Started

Over the past year, working with Node WebKit has become much easier because of tools like Yeoman. You can visit the Node-WebKit GitHub repo and read up on how to start building a new project, or you can simply use Yeoman to crank out a nice Node-WebKit starter project for you.

Before you start though, there are a few prerequisites:

  • Install Node.js (of course)
  • Install Yeoman globally: npm install –g yeoman
  • Install the Yeoman Node WebKit Generator globally: npm install –g generator-node-webkit
  • Install Node WebKit globally: npm install –g nodewebkit
  • Install the Grunt CLI globally: npm install –g grunt-cli

With all of this setup, go ahead and create your project directory. I’ve called mine “nwkit-example.” Go into that directory via the command line and enter the command: yo node-webkit. As you can see, you’ll be asked a few questions as Yeoman goes through and sets up your application. Be prepared to wait a little at the end – the WebKit downloads take a minute or two to come in.

Running the Yeoman generator for Node Webkit

Running the Yeoman generator for Node Webkit

After running the generator, you can see that an entire sample project is set up and ready to go. I’ve loaded the project into my favorite IDE, WebStorm. Of course, your favorite IDE or text editor will work just fine as well.

The files and folders generated by Yeoman

The files and folders generated by Yeoman

With a working project set up, you’ll want to run it. There are two ways to go about this. Either package up your application in an executable or run your Web files (inside the”app” folder) against the Node Webkit executable. Obviously, since you’ll be constantly editing and tweaking files, you’ll want the quickest and easiest method, so choose the latter.

These executables live inside “resources/node-webkit/{your-platform}”. On Windows, for example, you could open nw.exe via the command line with the arguments pointing to your app folder. There is an easier way – and that’s why we installed Node WebKit globally before.

From the command line in your project root, type nodewebkit app. This will run your app folder (with all of your HTML/JS/CSS files) against the globally installed Node Webkit, giving you your application window.

Running the Yeoman generated desktop app.

Running the Yeoman generated desktop app.

I won’t even get into the obvious step here of doing a “Hello, World”. You can see from the screenshot that the default HTML entry point is in app/views/index.html. If you wanted to add some text to this view, go ahead and try – you’re all familiar with adding text to an HTML page, right?

See Also:  Getting started with Redux using the Mullet Stack

Speaking of the tool/address bar, how do you hide it? I’ll tell you, but before you do, realize that it’s fantastic for debugging your application, so don’t be too hasty. In addition to the address bar, the menu button on the right offers the same developer tools you’d expect from Chrome or Safari. Therefore, I’d suggest only hiding these items when you want to put the finishing touches on your project.

In order to hide the toolbar, you’ll need to edit the the app/package.json file. This file controls a bunch of different options you can set for how the application is wrapped. You’ll see window size, minimum window size, title, and more. What you won’t see is a toolbar: false argument in the window object. If you add this, your toolbar will disappear.

Tweak it and look at the output.

The generated app running without the address bar.

The generated app running without the address bar.

Lastly, let’s take a look at how to package an application. As a prerequisite, you installed the task-runner Grunt. If you do web development, it wouldn’t be shocking for you to have already had this installed. I’ve got to hand it to the folks that made this Yeoman Generator—having a Grunt task to do various things with Node WebKit is very handy!

If you’re on Windows right now, choose the task “dist-win” (as opposed to “dist-mac” or “dist-linux”). From the root of your project, type:

grunt dist-win

Here’s what you get:

Running the task to package our desktop app.

Running the task to package our desktop app.

 

The files within the distribution package on Windows.

The files within the distribution package on Windows.

I’ve expanded the zip output so you can see some of the files. There are a couple of interesting things here in the .dll files (or probably .so files if you’re on Linux or OSX). For example, FFMPEG is a well-known library for doing video encoding and decoding, and libGLE handles OpenGL. These libraries handle HTML5 video and WebGL respectively. So it’s nice to know that those HTML5 features are still there when working on a desktop application.

Now that you are up and running for building some basic desktop application goodness driven by Node-WebKit, let’s look at building a better example.

An Example Application

Let’s move beyond the “Hello, World” application – or rather your blank application created above- and get into some of the real capabilities that you can’t get in your browser or Node.js alone.

At the start of this article, I was getting excited about the possibilities for combining my favorite tools and libraries in the browser with the power of Node.js. Currently, AngularJS and Angular Bootstrap are my favorite ways to start an application – and they work perfectly here (again, yay, WebKit!). But, what to build?

Lately I’ve been working on a mobile game of sorts using Cordova/Phonegap. I’ve been needing a way to get console.log output from my mobile device onto my desktop machine so that I could debug what’s going on. I’d looked into Weinre, and it’s a great project, but I have to set things up every time I sit down to debug. Easy things, too, like making sure my mobile device is on the same wifi network, looking up the IP address and adding it to my mobile app, and starting up the Node.js-based Weinre server. It’s not that difficult, but I preferred using ADB since I’m focusing on Android right now. ADB creates a bridge, typically over USB, between the device and the Android SDK, provided there is an ADB server on the machine.

If you open a command line prompt and type in adb logcat, you’ll see a massive number of log messages from your device. I thought it would be nice to create a UI wherein you could see, filter, and format the incoming messages. I don’t care about 99.9% of the Android logs that come in, I just want to see the ones that come from a Javascript console.log.

I’ve briefly looked up other ways to do that and couldn’t come up with anything. The ADB server Chrome App looked promising, but here’s what I see when I go to the Chrome store:

Trying to install the ADB Server Chrome app.

Trying to install the ADB Server Chrome app.

Oh well, why not see what we can do with Node-WebKit!

See Also:  Getting started with Redux using the Mullet Stack

ADBKit

Did I mention I love the Javascript/Node.js community? Well, I do. Anything you could possibly want to do seems like it’s been done, and you can find it on npmjs.org. To interact with ADB in Node.js, I found ADBKit. It’s described as “a pure Node.js client for the Android debug bridge”.

Using ADBKit, I started the ADB server (assuming the Android SDK is installed) to get a list of my connected devices and finally open up a connection to logcat for a specific device. Even better, ADBKit provides a nice little listener to notify me when each and every log entry comes in.

Pretty powerful and nice for a Node.js library, but what about the visual layer? Getting this far requires some basic knowledge of using Node.js and npm to get ADBKit installed and start using it. Going even farther into the WebKit side of the project involves some AngularJS skills. I won’t bore you with that, but I will share a Gist to prove a powerful point about Node WebKit.

https://gist.github.com/bengfarrell/8777742

In the Gist, I’ve included what’s called a “service” in AngularJS. It’s pretty commonplace stuff in Angular,  sort of like a Singleton that provides me with features anywhere across my application. Within the code, I’ve indicated a couple places where I’ve sprinkled in some Node.js to show how it interacts with ADBKit. The fact that I had to point out where this code is means there really is no dividing line in my application between Node and WebKit. Placing stuff that would only work through Node.js inside an Angular construct is crazy if you think about it. Here I have a framework (Angular) that’s designed to run in a browser, but I’m running it in on a desktop application while simultaneously running code that would only run on a Web server. At the least, I might expect to need some crazy workarounds, but no, it runs flawlessly.

The Android Whisperer

So in the end, I have a project I’ve dubbed “The Android Whisperer” built over a couple nights with Node.js, Node-WebKit, Angular, and Bootstrap. It’s definitely not perfect. It crashes when I press the button to start the ADB Server, but once I kick it off again, I’m rolling in log messages from my favorite Android device.

Log output unfiltered.

Log output unfiltered.

And then if I change the filter to “jsconsole”, I can see my Javascript console.log output:

Log output filtered to jsconsole.

Log output filtered to jsconsole.

That’s extremely useful because I’m trying to log things that use my mobile device’s accelerometer, compass, and gyroscope that I just can’t test on my laptop.

The other cool thing about this project is that I don’t have to show log messages. I could make an HTML5-based app or Website that uses console.log events to trigger events over ADB. You’ve seen mobile devices being used as joysticks or controllers for big screens. Those typically function over Websockets. With ADBKit and Node WebKit, we can plug right in! Maybe using ADB isn’t better than Websockets, but it certainly provides one more option.

Even More Possibilities

Obviously you can go beyond Android logging with Node Webkit. The possibilities are endless, and there are countless Node plugins at npmjs.org. The prospect of putting a front-end on any of them is just awesome. The flavor of front-end is unlimited when smart folks in the Web community seem to be putting out new frameworks and tools every day.

I’ve actually published a plugin through NPM called NuiMotion that allows you to track a user’s skeleton with a 3D-sensing camera like the Kinect. That was an interesting project because it was my first attempt at wrapping an existing C++ library for use in Node.js. That plugin is relevant to this discussion because not every Node.js plugin works right out of the box in Node WebKit. ADBKit, as you’ve seen, works great because it’s written in pure Javascript. My plugin, and others like it, require a compilation step to go from C++ to .node file. The process to make one is pretty easy, and it happens all the time when dealing with Node.js. When using an npm install, the plugin is downloaded but it also might need a build step to compile for the platform. That compilation is done using something called “node-gyp”.

But node-gyp doesn’t work with Node WebKit. Instead, the creators of Node WebKit have given us a tool called “nw-gyp”. It runs the same exact way, just swaps in “nw” for “node” in the command prompt. Just know that if you wade deep into these waters, you may have to compile a plugin here or there with this new utility.

Even with that extra step, I’d say that Node WebKit can do pretty much anything. Check out these applications and companies that use Node.js + WebKit to make things that couldn’t have been done with either one alone.

I hope you’re all inspired to do some cool things with Node WebKit. Use it with your favorite Javascript library. I recommend AngularJS, but you don’t have to listen to me. Use whatever you like!