5 min read

NW.js (formerly known as node-webkit) is a framework that makes it possible to write multi-platform desktop applications using the technologies you already know well: HTML, CSS and JavaScript.

It bundles a Chromium and a Node (or io.js) runtime and provides additional APIs to implement native-like features like real menu bars or desktop notifications.

A big advantage of having a Node/io.js runtime is to be able to make use of all the modules that are available for node developers. We can categorize three different types of modules that we can use.

Internal modules

Node comes with a solid set of internal modules like fs or http. It is built on the UNIX philosophy of doing only one thing and doing it very well. Therefore you won’t find too much functionality in node core.

The following modules are shipped with node:

  • assert: used for writing unit tests
  • buffer: raw memory allocation used for dealing with binary data
  • child_process: spawn and use child processes
  • cluster: take advatage of multi-core systems
  • crypto: cryptographic functions
  • dgram: use datagram sockets – dns: perform DNS lookups
  • domain: handle multiple different IO operations as a single group
  • events: provides the EventEmitter
  • fs: operations on the file system
  • http: perform http queries and create http servers
  • https: perform https queries and create https servers
  • net: asynchronous network wrapper
  • os: basic operating-system related utility functions
  • path: handle and transform file paths
  • punycode: deal with punycode domain names
  • querystring: deal with query strings
  • stream: abstract interface implemented by various objects in Node
  • timers: setTimeout, setInterval etc.
  • tls: encrypted stream communication
  • url: URL resolution and parsing
  • util: various utility functions
  • vm: sandbox to run Node code in
  • zlib: bindings to Gzip/Gunzip, Deflate/Inflate, and DeflateRaw/InflateRaw

Those are documented on the official Node API documentation and can all be used within NW.js.

Please take care that Chromium already defines a crypto global, so when using the crypto module in the webkit context you should assign it to a variable like crypt rather than crypto:

var crypt = require('crypto');

The following example shows how we would read a file and use its contents using Node’s modules:

var fs = require('fs');

fs.readFile(__dirname + '/file.txt', function (error, contents) {
  if (error) returnconsole.error(error);

  console.log(contents);
});

3rd party JavaScript modules

Soon after Node itself was started, Isaac Schlueter, who was friend of creator Ryan Dahl, started working on a package manager for Node itself. While Nodes’s popularity reached new highs, a lot of packages got added to the npm registry and it soon became the fastest growing package registry.

To the time of this writing there are over 169’000 packages on the registry and nearly two billion downloads each month. The npm registry is now also slowly evolving from being “only” a package manager for Node into a package manager for all things Javascript.

Most of these packages can also be used inside NW.js applications. Your application’s dependencies are being defined in your package.json file in the dependencies(or devDependencies) section:

{
  "name": "my-cool-application",
  "version": "1.0.0",
  "dependencies": {
    "lodash": "^3.1.2"
  },
  "devDependencies": {
    "uglify-js": "^2.4.3"
  }
}

In the dependencies field you find all the modules that are required to run your application while in the devDependencies field only the modules required while developing the application are found.

Installing a module is fairly easy and the best way to do this is with the npm install command:

npm install lodash --save

The install command directly downloads the latest version into your node_modules/ folder. The –save flag means that this dependency should also directly be written into your package.json file. You can also define a specific version to download by using following notation:

npm install lodash@1.* or even npm install [email protected]

How does node’s require() work?

You need to deal with two different contexts in NW.js and it is really important to always know which context you are currently in as it changes the way the require() function works.

When you load a moule using Node’s require() function, then this module runs in the Node context. That means you have the same globals as you would have in a pure Node script but you can’t access the globals from the browser, e.g. document or window.

If you write Javascript code inside of a <script> tag in your html, or when you include a script inside your HTML using <script src=””>, then this code runs in the webkit context. There you have access to all browsers globals.

In the webkit context

The require() function is a module loading system defined by the CommonJS Modules 1.0 standard and directly implemented in node core. To offer the same smooth experience you get a modified require() method that works in webkit, too.

Whenever you want to include a certain module from the webkit context, e.g. directly from an inline script in your index.html file, you need to specify the path directly from the root of your project.

Let’s assume the following folder structure:

- app/
  - app.js
  - foo.js
  - bar.js
  - index.html

And you want to include the app/app.js file directly in your index.html you need to include it like this:

<script type="text/javascript">
  var app = require('./app/app.js');
</script>

If you need to use a module from npm then you can simply require() it and NW.js will figure out where the corresponding node_modules/ folder is located.

In the node context

In node when you use relative paths it will always try to locate this module relative to the file you are requiring it from.

If we take the example from above then we could require the foo.js module from app.js like this:

var foo = require('./foo');

About the Author

Max Gfeller is a passionate web developer and JavaScript enthusiast. He is making awesome things at Cylon and can be found on Twitter @mgefeller.

LEAVE A REPLY

Please enter your comment!
Please enter your name here