Leading the development of electron-react-boilerplate for over 5 years has taught me quite a bit about performance challenges with electron and pushing the envelope of its performance. Contrary to popular belief, I believe that electron apps can perform as efficiently, if not more efficiently, than native desktop apps (VSCode vs Sublime is a classic example of this).
Before reading this, its important to recognize that applications will certainly benefit a lot more from fundamental architectural improvements as opposed to the optimizations discussed here. If you'd like to read more about architectural improvements, read the slack posts in the "Classic Electron and JS Perf Readings" section below.
Strategies for Performance Improvement
Over the course of maintaining electron-react-boilerplate, I've noted the following strategies as the most impactful improvements to be made to electron apps.
1. Debugging Electron perf using devtools
Applying traditional browser performance debugging techniques to Electron apps is a good starting point. Reading the flame graphs of your application will help you undestand what parts of yor app you should start optimizing. You'll understand what the bottleneck of your application is: loading assests, parsing JS, evaluating JS, etc.
2. Reducing require calls
3. Deferring requires using lazy loading
This can be done in a number of ways. One way of reducing the up front cost of loading your application is to use route-based code splitting and an app shell architecture. While working as a consultant for companies that use electron-react-boilerplate, I've used route-based code splitting optimizations to bring down startup time from ~20sec to ~5sec.
4. Fallback to native node modules or WebAssembly
5. V8 Snapshots
In addition to lazily loading modules and reducing require calls, another moethod of improving the initial startup time of an electron app is taking V8 snapshots of the initial heap that is created when your application initializes and then reinitializing this heap snapshot everytime the application is started so the heap and the objects in it don't need to be reconstructed every time the application is started. The V8 team wrote a great article on V8 Snapshots, which I highly recommend reading. I'd also recommend checking out electron-link, a piece of electron infrastructure which eases the process of leveraging V8 Snapshots with electron.
📚 More Readings
For thoses that want to read more in-depth articles on optimizing the performance of Electron and browser apps, I recommend checking out the following links.
🙇♀️ Case Studies
📖 Classic Electron and JS Perf Readings
- VSCode's Text Buffer Reimplementation
- Seena Burns: Debugging Electron Memory Usage
- Seena Burns: Thumbnailing is Isolate: Background Workers in Electron
- Maybe you don't need Rust and WASM to speed up your JS
- Oxidizing Source Maps with Rust and WebAssembly
- Slack: Chrome Tracing for Fun and Profit
- Performance Calendar: A collection of front end performance posts
- How we parallelized our node service by 30x
- 600k concurrent websocket connections on AWS using Node.js
- I have been underestimating JS Performance