Lessons learned from detecting node-webkit

Since I seem to writing posts on detecting various frameworks lately, I thought I would share some JavaScript code I’ve been using to figure out if the currently running HTML5 context is node-webkit or not. Like the other Cordova post, this too will cover some other solutions I came across in my research.

Similar to many other rendering engines, Node-webkit can change its user-agent string. This means that looking at the navigator object for testing is fairly useless: a project can pretend to be any other browser or rendering software through a setting in its package.json configuration. In fact, Node itself can be turned off from a simple setting in the same file.

With those two issues in mind, then, testing becomes about two goals:

  1. Detecting if Node.js is part of the running context
  2. Detecting if the environment is Node-Webkit.

Detecting Node.js

Does process exist?

var isNode = (typeof process !== "undefined");
view raw process.js hosted with ❤ by GitHub

Code running under Node.js will generally have access the global variable process. This provides information as well as access to functions related to the running process such as standard input and output. If it exists, chances are good the running context is probably Node.js.

Does require() exist?

var isNode = (typeof require !== "undefined");
view raw require.js hosted with ❤ by GitHub

Like checking for process, the function require() is nearly always around in Node too. Because it is part of the core module loading functionality, it is very rare for require() not to to exist in a Node running context.

However, it is also common for developers to use Require.js or similar libraries, so testing exclusively for a global require() function is not as useful as it might first seem.

Checking for both process AND require()

var isNode = (typeof process !== "undefined" && typeof require !== "undefined");
view raw detectNode.js hosted with ❤ by GitHub

Combining the two approaches creates a reasonable detection requirement. If both process and require() exist, the environment is most likely Node.

Detecting Node-Webkit

Checking for ‘nw.gui’

var isNode = (typeof process !== "undefined" && typeof require !== "undefined");
var isNodeWebkit = false;
//Is this Node.js?
if(isNode) {
//If so, test for Node-Webkit
try {
isNodeWebkit = (typeof require('nw.gui') !== "undefined");
} catch(e) {
isNodeWebkit = false;
}
}

With code in place to detect Node, detecting Node-Webkit itself is fairly simple. Since all compiled binary versions of Node-Webkit will have the “nw.gui” module, this means that testing for it becomes a great way to determine if the running context is Node-Webkit.

However, since it is entirely possible that the running context might be Node without also being Node-Webkit, putting a try-catch around the code allows for testing if the “nw.gui” module is loaded and, if not, to catch that exception and move forward without crashing anything else.