How does Node.js work with NW.js and Electron?

This article has been excerpted from Cross-Platform Desktop Applications

Those who’ve used Node.js in the past may be curious about how it works in a hybrid desktop application environment such as NW.js or Electron. The truth is it’s not that different from how it already works in server-side applications, but there are a few items of difference, and to understand what those are and why this is the case, we’ll start by looking at the way Node.js is integrated into NW.js.

Where Node.js fits into NW.js

NW.js’ architecture consists of several components, Node.js being one of them. The way that NW.js makes use of Node.js is to provide a way to access the computer’s file system and other resources that’d otherwise be unavailable due to web browser security. It also provides a way to use many libraries through npm.

An illustration of how Node.js is used within NW.js for desktop apps

NW.js makes Node.js available through the context of the embedded web browser, which means you can script JavaScript files that access both Node.js’ API, as well as API methods related to the browser’s JavaScript namespace, such as the WebSocket class. One can write code that accesses Node.js’ Filesystem API in the same file that also accesses the DOM in the screen.

This is possible through the way NW.js merges the JavaScript namespaces of Node.js and the Blink rendering engine, as well as merging the main event loops of both, allowing them to operate and interact in a shared context.

Caveats of using Node.js in NW.js

Because of how NW.js merges the JavaScript contexts of the Blink Rendering engine and Node.js, you should be aware of some of the caveats that come with this approach. We’ll describe what those things are, and how you can handle them without tripping yourself up.

The Node.js context is accessible to all windows

We’ve talked about Node.js and Blink sharing the same JavaScript context, but how does that work in the context of an NW.js app with multiple windows?

In Blink, each window has its own JavaScript context, as each window is loading a web page with its own JavaScript files and DOM. The code in one window operates in the context of that window only, without its context leaking into another window — otherwise this would cause issues with maintaining state in the windows, as well as security issues. We expect the state that exists in one window to remain isolated to that window.

That said, NW.js introduces a way to share state between windows, via the way Node.js’ namespace is loaded into the namespace of Blink to create a shared JavaScript context. Even though each window has its own JavaScript namespace, they all share the same Node.js instance and its namespace. This means you can share state between windows through code that operates on Node.js’ namespace properties (such as the API methods), including via the require function used to load libraries. If you need to share data between windows in your desktop app, you’ll be able to do this by attaching data to the global object in your code.

Common API methods in Chromium and Node.js

You might know that both Node.js and Blink have API methods with the same name and that work in the same way (e.g. console, setTimeout, encodeURIComponent). How are these handled? In some cases, Blink’s implementation is used, and in other cases, Node.js’ implementation is used. NW.js opts to use Blink’s implementation of console, and for setTimeout, the implementation used depends on whether the file is loaded from a Node.js module or from the desktop app. This is worth keeping in mind when you’re using those functions — although they’re consistent in their implementations of inputs and outputs, there might be a slight difference in speed of execution.

How Node.js is used within Electron

Electron uses Node.js along with Chromium, but rather than combining the event loops of the two pieces of software together, it combines them through Node.js’ node bindings feature. In this way, the Chromium and Node.js components can be updated easily without the need for custom modification of the source code, nor compilation afterwards.

In regards to how Electron handles the JavaScript contexts of Node.js and Chromium, it keeps the backend code’s JavaScript state separate from that of the frontend application windows’ state. This isolation of the JavaScript state is one of the ways that Electron is different from NW.js. That said, Node.js modules can be referenced and used from the frontend code as well, but it’s operating in a separate process to the backend. This explains why data sharing between the backend and application windows is handled via inter-process communication or “message passing” as it’s also called.

If you’re interested in learning more about this approach, checkout this site from GitHub’s Jessica Lord: http://jlord.us/essential-electron/#stay-in-touch

You can also see more by downloading the free first chapter of Cross-Platform Desktop Applications and a discount code can be found in this Slideshare presentation.

Show your support

Clapping shows how much you appreciated Paul Jensen’s story.