Multi-platform Development (Electron/NW.JS)

Frameworks in Vending Machine
Vending machine created by macrovector - www.freepik.com, Logos are owned by there respective companies.

About this Series

If you haven't read the intro, I discuss a lot of the core information about this, I have included the Raw Stats in each of the blog posts so you can easily reference it while reading about each of the products.

Raw Stats

PlatformAppImage File SizeHello Memory AppImageHello Memory UnbundledGraphic AppImageGraphic Unbundled
Electron97 Megs203129401316
NW.JS110 Megs274163515389
Tauri71 Megs19252364301
NodeGui47 Megs43753760467
Yue19 Megs5943302292
Node-GTK100 Megs85709089
Flutter70 Megs12453337321

Thoughts on Electron & NW.JS

Electron (& NW.js) really gets a bad rap in a lot of cases, but in all reality for what it does, it is actually well built. For a very long time I was on the band wagon that NS.JS/Electron apps are bad. Yes, they do waste memory as each app can't share memory with other browser instances as they are all isolated. I'm normally all about performance. But sometimes development resources and time to deploy need to be taken in consideration.

Unfortunately building a cross platform application is very hard. Any interface that runs html is actually extremely complex and will just chug memory, I don't care what browser you want to use. As you can see from the above every single app that was more complex then "Hello World" were all using over 300megs of memory, and most where pretty close to each other. Unless you are going native, and especially eliminating a WebView you are going to be using around the same amount of memory.

Building a fairly simple Electron application created a AppImage of 97 megs and while running it used a total of 203 megs of memory. NW.JS was actually a larger AppImage of 136 and really ate the memory at 348 megs, however maybe that is something to do with the AppImage bundle as the more libraries that is in the bundle the less is shared with the OS, it is something on my list to check out since unbundled the memory usage was very close to the rest of the pack...

By embedding the exact same Chromium/v8/nodejs engines on all three platforms, your HTML, CSS and JS will work exactly the same on all the platforms, eliminating costly time dealing with weird behavior on a single platform. In addition any OS updates to its native WebView will not affect your application. As such, you application easily runs on older OS versions as well as probably working perfectly fine on unreleased new versions for many years in the future.

Electron is the best supported and at this point Electron is probably the best of the bunch for actually being productive and getting something out. Although NW.js is not to be ignored, it does offer some features (like source code protection) that Electron doesn't. So play with both of them.

Development on Electron

The nice things about Electron is the ability to quickly iterate, many tools can do hot loading in Electron. Electron has "3" separate entry points, a Back end (Node), Front end (Chrome) and a temporary Preload (Node) . The Preload allows you to expose some node stuff to the Front end so that you can create helper functions that are pre-loaded and then the front end can call directly without exposing the entire node to the front end. Otherwise the front end is sand boxed to chrome and has no direct access to node so that it is basically like running everything in a chrome. You can send IPC's internally from the front end to the back end.

Development on NW.JS

NW.JS is a bit different, it has two different types of windows. The first type of windows is just like Electron's front end, it is just a Chrome window no access to Node. And then it has what it calls Node-Frames, these are Chrome & Node merged, basically like the temporary Preload you have in electron, other than it is permanent for the lifetime of the window. When opening a window you can choose the type of window you want. In addition, there is a "webview" component this allows you to create a new context that isn't shared by your app to view third-party content. So, in this it I believe it has a bit better security than Electron. However, as you might have noticed from the table, NW.JS seems to always use more memory than Electron. I suspect Electron has worked hard on reducing its memory size, where NW.JS has been focused on other items.

Security

NW.JS offers more ways to run your app and more ways to secure or (make your app less secure depending on your needs). So it is much more flexable over Electron, in fact you can even run everything in a single process, which might even use less memory (I haven't tested this). NW.JS is also typically running the latest Node and Chromium within a day of one of those releases, so bug fixes and features come to NW first. Electron is more cautious about releases.

Building on Electron

Building a AppImage for Electron, is fairly simple, just install electron-builder and you can build pretty much any type of image you want. It supports multiple outputs for Windows, Mac and Linux without any issues.

Building for NW.JS

This was a lot more painful, I had to manually create a structure and customize the yaml files, run the AppImage specific tooling. All in all it was a pain, but once you have it automated it should be fairly simple. However, you have to figure out the tooling for each OS. There is a built in NW file package that can be used, and it might be enough for your purposes, but a AppImage is one of the safest methods for at least Linux.

I am curious to know if electron-builder could be easily re-purposed for NW.js as the packaging should be virtually identical on all platforms with only a couple minor changes in the layout. In fact I tested the Electron image electron-builder generated, and was able to just replace Electron with NW.JS and the image worked the same. But it would require some re-tooling in the project to make it work fully with NW.JS...

Summary

I do really dislike the memory footprint of these, if you are doing a tool you might consider using some framework that does NOT use a webview for displaying your UI. Node.JS is only uses about 10 megs of memory, so for CLI tools it is actually pretty decent. Unfortunately if you are set on using JavaScript as your language, and using some HTML/CSS layout for display, I'm not sure a great solution for you and if you have any ideas, I'd love to review them.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.