RepoCMD: Adventuring into Electron
I'd been wanting to develop an Electron app for a while. Not just any app though—a proof-of-concept to mitigate some of the known shortcomings of working with Electron:
- Performance: Dealing with Electron's resource intensive footprint.
- Privacy: Working around Electron's inability to conceal source code.
- Versatility: Decoupling business logic from Electron's architecture.
Accepting the Performance Trade-off
Having started my career as a native desktop developer, I didn't expect Electron to match native performance.
I anticipated Electron to be more resource intensive since it depends on Chrome processes at runtime.
Knowing all this, I was willing to sacrifice a moderate amount of performance for the familiarity of a web stack and a single codebase.
Coming to accept the trade-off is an important step in accepting Electron as a viable option for production. As developers, we tend to forget that performance issues are the last thing end-users want to experience. Most of the world doesn't run on Macbook Pros and 16GBs of RAM, so we better be extra careful with vital resources.
By the way, there's also the small caveat of giving up 100MB+ worth of filesystem space right off the bat. Fortunately, it's a one-time cost of doing business and we have other things to think about.
Dealing with Privacy
Electron apps are bundled using a tar-like archiving format called asar.
I initially failed to realize that asar archives can be easily unpacked. That means source code is visible to anyone curious enough to see. That's fine if your application is open source, but it can be a potential pitfall for businesses wanting to protect their competitive advantage. It's also worth considering that as long as humans work on source code, there's an eventual risk of exposing sensitive data.
Fortunately, like most things in the tech world, there are workarounds. During research, I read that V8 JS snapshots could be used, but it wasn't immediately obvious how to do it.
Call me a weirdo, but I always run into this line of thinking: "What if Electron disappears and I'm left with all this code from yesterday?" Yeah, it's unlikely that Electron will disappear, but what if something better comes along? How portable can my code be to attempt a possible transition?
To be fair, this isn't an Electron issue. It's a developer issue. So, I decided to approach Electron as a GUI toolkit that should be kept decoupled from an application's business logic.
Finally, a Thought
Here's where I tried to get creative: I decided to build all of my application's business logic into a single binary that could be executed from Electron's main process.
Go seemed like a perfect fit. I could leverage its cross compilation features to target all major operating systems. I'd bundle them as unpacked files in Electron and expose functionality through a traditional web API.
I took it a step further: what if I had a standalone SPA and my standalone binary living inside of the Electron app? I can have my view layer decoupled from my business logic, while having it all bundled within an Electron executable.
I could then tackle most of the initial issues I was concerned about:
- Performance: Depending on the use-case and going avoiding the Go vs. Node comparisons; Go is significantly better at CPU-bound computation.
- Privacy: I'd be concealing business logic by distributing it as machine code, a step up from obfuscation.
- Versatility: Having all business logic living in a single binary means portability. Also, having a Vue handle the UI means that a standalone SPA can be made at any time.
Other possible advantages:
- The binary can handle most of what the Electron API does regarding I/O.
- The Go x Vue combo could be moved to the cloud and repurposed as a web client.
- A CLI could be worked into the Go binary and used elsewhere.
Sounds good, have anything to show?
Yes, as a matter of fact, I do. I went ahead and created RepoCMD, a GitHub management app as a proof-of-concept.
Find the Electron app here: github.com/repocmd-desktop
And the Go application here: github.com/repocmd
I'll be working on part 2 of this series, where I go into a technical walkthrough explaining how all of these components work together.
In the meantime, you can follow me on twitter for updates: @_ef2k.