How to Build Desktop Applications the Right Way Using Electron

Kick off your next project with Electron

Juan Cruz Martinez
Nov 19, 2020 · 6 min read
Electron home page
Electron home page
Photo from Electron.

If you are like me, you love JavaScript and its ecosystem and have been building amazing web applications using frameworks like React or performant web servers with Node.js. Now you want to develop a desktop application and you don’t want to learn a new programming language. Or perhaps you want to reuse as much as you can from existing web projects.

Here is when Electron enters the picture to save the day.

Electron allows you to build desktop applications using HTML, CSS, and JavaScript. There are many arguments on the internet against Electron, some of them being its performance and often low-quality apps, but don’t blame the framework. Electron is powerful and can be performant. Today, many popular applications run on top of Electron, such as VS Code, Slack, Skype, Discord, and more.

But why is it then that many people argue against it? The problem starts with the apps and the way people use Electron. For many, porting a web application to an Electron means taking your existing code as is and embedding it into an Electron container. Is this a terrible thing to do? Maybe not, but you are not taking full advantage of the power of Electron. You are merely changing a browser tab for an independent application.

What can we improve? In this article, we will explore the basics of Electron and build a sample application to show some of the Electron ways.

How Does Electron Work?

Electron is built on top of three main components:

  • Chromium: Responsible for the web content.
  • Node: For interacting with the OS.
  • Custom APIs: To solve for common issues when dealing with the OS.

Each of these components interacts on a different level on the Electron architecture layer, as shown in the architecture diagram:

Electron’s architecture
Electron’s architecture
Electron architecture

Electron works with two types of processes:

  • Main process: Responsible for window management and all interactions with the OS. It’s where it all starts, and it can create and manage multiple renderer processes.
  • Renderer process: There could be one or more. Each will host a Chromium instance and be responsible for the web contents.

It’s important to note that the renderer processes cannot access OS features directly. Instead, they communicate with the main process through IPC to achieve these tasks.

Many typical Electron applications would use the main process to create one renderer process and load their web application. Today, we are going to take that one step further.

Must-Have Section: Hello World!

Next, we are going to build a “hello world!” application. We will not use any framework or libraries that are not necessary to stay focused on the Electron code.

Let’s get started.

Setting up Electron

The first step to building an application is to create a project and install the Electron library, so start with the project creation using NPM:

npm init

And set up your application details. As the starting point for the application, I like to use main.js, but you can use any file name you want.

Next, install Electron:

npm install -D electron@latest

Building the screen

For our micro hello world example, we need two files: main.js and hello-world.html. main.js is our main process. We will create the first renderer process that will load our hello-world.html.

Here is the starter code for main.js:

The starter kit will handle the minimum operations to run the application, creating the first renderer with new BrowserWindow and loading main.html on it. It will also address some scenarios to exit the application and relaunch the main window when needed.

As for our main.html, we will use the following:

It is just a simple HTML exposing the current versions of Node, Chrome, and Electron that our app uses.

Finally, we need to run our application. First, you need to change the package.json and add the start script:

"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},

Your “scripts” section should now look like that.

Time to test it! On a terminal, run:

npm start

If everything worked out well, you should see a window like this:

Hello World app
Hello World app
Hello World app made with Electron

Isn’t there an easier way?

The short answer is yes, though it comes at a cost. Many boilerplates provide a starting point for building Electron applications — some of them using vanilla JS, others directly integrated with some of the most popular frameworks like React and Vue.

I’m not a big fan of these boilerplates, as they often come with many libraries and additions I don’t need. But they are a great place to get you started.

Here are some popular ones:

Building Smooth Applications

We already saw how things work in the architecture of Electron. And if you are like me, you are probably worried about all those instances of Chromium and Node running — and you should be. We all know how Chromium (or Chrome) can devour our memory and affect our performance, so what can we do to avoid our Chromium-based application doing exactly that? How do we keep it performant?

Here are a few tips.

Never, ever, block the main process

The main process is where it all starts. It is the parent process for all the processes of the application. It is the one that communicates with the operating system, handles all the windows and communications between them, and runs the UI thread.

Blocking this process means that the application will stop responding until the operation finishes. Under no circumstances should you run code that is CPU-intensive and takes a long time to complete here.

Here are some recommendations:

  • For CPU-intensive operations, delegate those functions to either a worker thread, a renderer process, or even spawn a dedicated process to perform that task (though make sure you know what you are doing for this last one).
  • Avoid the use of the remote module as much as possible. It is far too easy to unknowingly block the UI thread using the remote module.
  • Avoid using blocking I/O operations on the main thread. If needed, use the asynchronous equivalents provided by Node.

Is it OK to block the renderer process?

Not really. Perhaps the consequences won’t be as harmful as blocking the main process, but blocking the renderers comes at a price. Your windows may become sluggish or unresponsive, and the overall user experience will be terrible.

When we use the web, we are used to some web apps suddenly going slow, not being smooth, and we are OK with it. However, when it comes to desktop applications, our standards are higher. Be aware of this, as user expectations matter.

What can I do to make my apps more responsive? Pretty much the same things we could do on our web apps. After all, on the renderer process, we are just talking about Chromium.

  • requestIdleCallback: This is an API allowing the execution of JavaScript to be queued to run in idle browser time, either at the end of a frame or when the user is inactive.
  • Web workers: The best tool to run expensive computations on web browsers by assigning them to a new thread.

You don’t need cross-browser compatibility

During web development, it is very typical to use polyfills to support different browsers. When building Electron applications, you don’t need any of that. If it runs on Chromium, it runs on Electron and there’s no need to support any other browser. Reduce your bundles and make everything faster by not loading these extra modules.

Bundle all of your code

In web development, we sometimes load scripts or pages from servers like CDNs, which are served separately from our application — and that’s fine. After all, for the web, we always need to download these assets to run the application.

For desktop applications, this is different. Avoid any unnecessary network requests by bundling all your static assets, scripts, and contents in your application. This will enable your app to do two things: work offline and speed up the loading process, as reading the disk is cheaper than going to the internet.

Conclusion

Next time you need to build a cross-platform desktop application, I recommend you try Electron — especially if you are coming from JavaScript and already have some code you may be able to reuse.

Electron can be great if used right. Keep in mind that though it looks like web, it is not precisely that and thus you will need to make some special considerations to make it work.

Thanks for reading!

Better Programming

Advice for programmers.

Sign up for The Best of Better Programming

By Better Programming

A weekly newsletter sent every Friday with the best articles we published that week. Code tutorials, advice, career opportunities, and more! Take a look

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Juan Cruz Martinez

Written by

I’m an entrepreneur, developer, author, speaker, and doer of things. I write about JavaScript, Python, AI, and programming in general.

Better Programming

Advice for programmers.

Juan Cruz Martinez

Written by

I’m an entrepreneur, developer, author, speaker, and doer of things. I write about JavaScript, Python, AI, and programming in general.

Better Programming

Advice for programmers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store