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:
- Detecting if Node.js is part of the running context
- Detecting if the environment is Node-Webkit.
Does process exist?
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?
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()
Combining the two approaches creates a reasonable detection requirement. If both process and require() exist, the environment is most likely Node.
Checking for ‘nw.gui’
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.