There are a lot of posts about NodeJS describing innovative solutions about JavaScript on server side. However there is another place where JavaScript, V8 and Chrome HTML engine can be applied. That place is your desktop and Electron is a technology that makes possible to create desktop applications with JavaScript/HTML. I’m sure most of us already have experience in Electron. I’m sure that everybody who is reading have at least one Electron based application on this desktop. And some of that applications are really awesome. For example Visual Studio Code, Slack or Atom the beginning of Electron platform. So I’m a little late with this post, but let me share some of my problems and way to solve them.
What is Electron?
According to documentation Electron is NodeJS and Chromium tunning on the same V8 engine. As result we have something like possibility to run node modules in browser. That will allow to access local file system or use any C/C++ modules.
Any Electron application has at least two processes, one main process and one or more renderer. The main process is pure NodeJS process and entry point of the application. Main process is responsible of creation of windows and every window has it’s own renderer process.
In renderer process you are inside Chrome browser but with power of NodeJS.
You can easy communicate between processes with IPC. Electron gives you very simple API for this.
I think that is more that enough about Electron to have general picture of it. You can try it with this tutorial http://electron.atom.io/docs/tutorial/quick-start/.
Asynchronous operations
It is very hard to imagine modern desktop operation without asynchronous operations. We need to show progress while loading something, we need to perform background calculations and many many more features like these. However Electron is not so good in asynchronous operations.
One of the first idea to do something in async way is to send IPC message to main window and wait for results. You may not believe me if I will say that this may freeze your UI but consider following sample
https://github.com/peleshenko/freezing_node_sample
Clone it run npm install and execute run.sh.
When we are trying to freeze UI with long running loop you can not type in input field but css animation is working and you can close window. But when we are trying to freeze application with long running loop in main process even css animation is freezed and you can not close the window.
Amazing!
You can review corresponding discussion on Electron page on github https://github.com/electron/electron/issues/3363
Short answer:
... a blocking operation in main process is easy to block all other processes... ...it is required to put IO and CPU-bound operations in new threads to avoid this...
So the first lesson learn – forget about main process, live it alone, this process is for Chromium not for you, use your own.
Next idea is to use WebWorkers. Electron supports WebWorkers. But unfortunately in WebWorkers you have no access to NodeJS. You can use usual browser API, or calculate something but no NodeJS. That fact makes WebWorkers useless in Electron because most operations that requires async execution are related to file system or other external things.
So there are only one way start something in parallel thread using JavaScript is child_process.fork. Not very simple but working way.
Alternatively you can create a C/C++ addons and do anything you want inside this addon with C++, start any number of threads and dispatch results to Electron’s message loop with callback. But that is another story…
C/C++ Addons
As you can see addons is not something unusual even simple async operation may require addon creation. Additional reason that may enforce you to implement your own addon with C/C++ is quality of existing addons in npm. Some of them are really terrible.
After my last word I think you recall your last attempt of npm module installation in Windows. You had to install specific version of VisualStudio and Python 2.7. My first reaction was “What? The module author is crazy he is going to mix C++, Python and NodeJS. Give me another module…”. But all modules that has C/C++ code inside will require Python and VisualStudio and some times specific version of VisualStudio.
You need all this software to install module because of NodeJS build system node-gyp. That is the only way to include C/C++ addon to your npm module. That is strange thing but if you will take a look a little deeper you will understand the reason. But let me leave this topic for another post.
OK finally you installed VisualStudio and Python and installed module. Starting your Electron application and see following in dev tools console (numbers may differ):
Module version mismatch. Expected 48, got 47"
The source of that problem is that node addon is only compatible with exactly the same node version that this addon has been built for. And you just have built is for your NodeJS but Electron as a little different NodeJS version inside. Doh!!!
To solve the problem you can use electron-rebuild. Follow the instruction and you will be able to rebuild required module for NodeJS version used in Electron.
And the last…
That is it about Electron and problems with it in general. We have more and more projects with Electron in Tesseris Pro. So I hope to share my experience in C/C++ addons and React in Electron in next posts.
And once more. Electron is Chromium + NodeJS, thus it already has NodeJS module system and that system is not so bad. And as for me it looks very strange when people tries to use system.js or require.js or any other JavaScript module system to load modules in Electron. Electron is not a browser! It is NodeJS + browser! Use it as NodeJS!