Electron can be quite a complex beast.
It has a main process and one renderer process for each window that you open. The main process is a node.js process and is generally used to launch “renderer” windows and to help send messages between multiple windows. The render processes are essentially Chromium browser processes which you can run Aurelia in just like you would a webpage from a file://
url.
The docs here do a better job at explaining that than I can.
Eventually you’re going to want to allow your Aurelia app to access node.js features, otherwise why would you be using Electron.
If you are not loading remote content, you can enable full node.js support in the renderer processes too. This is by far the easiest way to use Electron but can result in some serious security vulnerabilities. This is because a cross-site-scripting attack or a vulnerability in any of your dependencies could result in full access to node.js and everything that allows (ie. file system, network, native code, etc
). It’s worth reading the security recommendations before you do this. It’s also worth remembering that “remote content” doesn’t necessarily mean “loading a remote web page”. If your app is a markdown editor and a security vulnerability is discovered in your markdown parser, somebody could create a malicious markdown file that could execute node.js code on users machines! Years ago, we found a serious security issue in our production Electron app due to an erroneous use of innerHtml
which would have allowed a specially crafted file to inject and run node.js JavaScript when it was opened!
If enabling node.js in the renderer is off the table, one option which became common was to treat the main process as a backend and do all the node.js stuff there and treat the renderer as a front end, much like a standard website with a server. You can then use Electron IPC modules (Inter Process Communication) to send messages back and forth between main and renderer rather than HTTP messages.
There are however some pain points with the above which you should be aware of. The most important is that you should not block the main process. It is NOT an isolated background thread for you to run long running blocking tasks on. As well as running your supplied main process script, it is also in charge of marshaling messages between the renderer and GPU processes. Block the main process for more than a few 10s of milliseconds and you’ll notice freezing in the front end rendering. If you do any file IO in the main process, ensure you use async calls so node awaits these on another thread for you.
There is another option which has become the recommended means to access node.js functionality from your web frontend. The Electron renderer processes can be passed a “preload” script which has access to node.js which can then expose certain functionality for your isolated web page to use later once it’s loaded. Exposing certain functionality from a node.js object without exposing a huge gaping hole is also fraught with danger so it’s recommended that you use the contextBridge
module to help you do this safely.
So yeah… there are many ways to skin this cat and they all involve footguns along the way.
Once things have calmed down at my end and I’m not so swamped, I want to collaborate with a few people and create a fully featured open source app with Electron + Aurelia using best practices. Ideally something that showcases the power of both.