Why I prefer NW.js over Electron? (2018 comparison)

32,750 reads

NW.js vs Electron (forgive the horrible design!)

In this post, I will give some objective reasons why I prefer working with NW.js (formerly node-webkit) over the other guy: Electron.

If you don’t already know, both projects are built on top of Chromium and Node.js, so that you can write desktop applications using Node.js at the system level (filesystem access, etc) and web technologies for the GUI layer.

Now, Electron has some advantages:

Electron is more popular among developers: Almost in every post or article I have seen, people preferred Electron. This is also clear from other metrics, like Github stars, npm downloads, etc. Electron has a better corporate support: Github / Microsoft are behind Electron, while NW.js is sponsored by Intel. The two most popular IDEs (VSCode ane Atom) are built using Electron. On the other hand, the only big project I knew that was built using NW.js was discontinued. I mean Intel® XDK of course. However, after talking to Roger Wang, the creator and the maintainer of NW.js, he noted that there are other “big” applications —both big in scale and have a huge active user base — built using NW.js, he noted that “the official IDE of WeChat Mini Program runs on NW.js. There are more than 1,000,000 Mini Programs developed with it. The Mini Programs runs on WeChat IM software, which has over 1 billion monthly active users. See more on TechCrunch”. Electron offers auto-update mechanism out of the box. Finally, its build process is a bit easier, because you don’t have to build the entire Chromium. For more information about this, check here and here. (However, most users do NOT need to build either NW.js nor Electron).

These are some reasons why someone would go with Electron. Now, let me explain why I would go in the opposite direction. NW.js — in my opinion — is better than Electron!

1. Legacy Systems Support

NW.js (LTS version 0.14.x) supports Windows XP and older versions of Mac OS. I know that even Microsoft has dropped XP support, but in many areas, many people are still using it (it has a huge market share in some countries). You can’t just tell your customers to upgrade! They won’t listen.

2. Application Main Entry can be both an HTML Page or a Node.js File

NW.js is more browser-oriented. You can set your main entry to be an HTML file or a Node.js file, or even both (using main , node-main and bg-script fields in package.json). In Electron, you have to use Node.js file and explicitly create your app main window and open it.

The approach of NW.js is a lot easier and more straightforward. It gives you many options. It allows you to do what you can do in Electron, but not vice versa.

3. Separate and Mixed Contexts

NW.js has a simple yet powerful mechanism in regards to JavaScript context. Electron has two separate contexts (main process and render process), that are completely separated. In NW.js, you have two options: separate contexts and mixed contexts. Both — in my view, again — are easier and more straightforward than Electron. You can build your whole app without the complexity of IPC messages.

The issue here is that NW.js Documentation on this point is very, very confusing. In fact, I wrote another draft blog post (will be published soon, hopefully) trying to clarify contexts in NW.js and how you can easily share variables and state between contexts and windows, in both modes: separate and mixed.

4. Chrome extensions and Chrome.* APIs Support

NW.js supports chrome.* APIs. Even better, you can run Chrome Apps/extensions using NW.js. Electron can’t (and won’t) do this.

5. PDF (and Flash) Plugins Out of the Box

NW.js supports PDF files out of the box, using Chrome PDF native plugin. It works so smoothly that you can even set "main": "file.pdf" and it will work. You can display PDF files inside <iframe> , <webview> , or just by pointing page location to a PDF file.

Electron, supposedly, added this feature in version 1.6.4. However, it is very buggy (check: 01, 02). I have tried many ways (using Electron v3.0.8) to display a PDF file inside Electron ( <iframe src='./file.pdf'> , <webview src='./file.pdf' plugins> and many others), but Electron keeps trying to download the file, not display it as expected. After an hour of searching around for a solution, I just gave up.

6. Source Code Protection

NW.js has a source protection tool. This allows you to compile your JavaScript to V8 bytecode (formerly it used to produce machine code). Electron guys, on the other hand, refused to implement this feature entirely.

However, I made a minimalist tool, bytenode, that allows Node.js developers (even in Electron) to compile their code into V8 bytecode.

Bytenode only compiles Node.js code, while JavaScript code that will run in the browser (via <script> tags) cannot be compiled using it. So, again, NW.js does a better job here, because their tool nwjc compiles browser-side JavaScript. Using both tools ( bytenode and nwjc ) you can compile your whole application, even third-party libraries (like jQuery).

7. NW.js Uses Latest Chromium Version

NW.js team is trying to keep up with Chromium version. So the day after a new version of Chromium is out, they will publish a new version of NW.js (with the latest version of Node.js that has the same V8 version as Chromium).

While you may not always need the latest Chromium release, many people do need that. It is clearly an advantage of NW.js.

Electron team, on the other hand, prefers to wait a few weeks or even months, before moving to a newer chromium version.

8. NW.js Has ‐‐url Flag and Supports Chromium Command Line Switches

You can start NW.js with --url flag:

/path/to/nw --url="https://www.google.com/ncr" to open a URI, so this is a third way to start your app (besides using an HTML page and a JavaScript file).

NW.js also supports all Chromium Command Line Switches. For more information, check NW.js docs. These switches can be used to tweak and tune performance.

Electron, on the other hand, does not have --url counterpart. You have to start your app with a JavaScript file, create your app window and navigate to the URI manually. It also does not support all Chromium Switches, only some of them are supported.

9. NW.js can be Distributed without Dev Tools

In Electron, you always have DevTools embedded in Electron binaries. It can be opened as easy as that:

mainWindow.webContents.openDevTools(); .

In NW.js, you would use the “normal” build in production, which does not include DevTools (only SDK build does). If someone tried to open DevTools programmatically:

nw.Window.get().showDevTools(); , he would find a blank white screen.

Yes, theoretically he could have used an SDK build, to run your application, but you can prevent this scenario in your code (by checking if process.version[’nw-flavor’] equals normal , combined with source code protection, check № 6 above). You can’t do this in Electron (please correct me if I’m wrong).

10. Printing PDF Files

If your application needs to print PDF files without headaches, you should go with NW.js. Printing works just as expected here, whether you are printing a webpage (using nw.Window.get().print() function), or you want to print a PDF file (using the native print button, as Chromium does).

On the other hand, Electron users are struggling with getting printing function works as expected. There are many open issues in Github on this problem (e.g. #9029). See also this StackOverflow question, it has some insane workaround that tells you to use PDF.js (Ouch!) to render its content on a canvas, then print that! Other workarounds suggest using SumatraPDF (Ouch again!). Again, correct me if I’m wrong, I have a little experience with Electron.

11. Better Security Model for Desktop Application

The security model in Chrome (and web browsers in general) is a bit restrictive, due to the nature of your relation to the websites that you visit. Browsers do not allow websites to have an access to your filesystem, websites run in a sandboxed environment, and they are subject to same-origin policy … etc. While this makes sense in the context of web browsers and website, desktop applications need more.

NW.js provides another security model, that allows you to “Bypass all security restrictions, such as sandboxing, same origin policy etc. For example, you can make cross-origin XHR to any remote sites, or access to <iframe> element whose src points to remote sites in node frames”, according to NW.js Documentation. According to Roger Wang: “The list of things we can do in this model is expanding, and it might be good to ask for proposals from developers in [your] article. Issue reports like this are welcome”.

Compare this to Electron, which disables features like nested <webview> tags (01, 02), because “it is a maintenance burden” and “it is not easy to get things right”. (by the way, you can nest webview tags in NW.js as you want, but for local HTML files, you have to add a permission in package.json ).

Finally, I’m a little biased towards NW.js. I hope this bias did not affect the accuracy of my article. Any comments or corrections are more than welcome.

Tags