Building Desktop Apps With Electron: Part 1

Anuj Baranwal
9 min readJul 31, 2018

In this series, we will be discussing about the Electron and how we can create desktop apps using it. Initially, we will be building two small apps with plain javascript and html. Believe me! That’s all you need to know to create your desktop app. Then we will move forward and start creating two more apps with React and Redux. We will also discuss the fundamentals of electron in between. A lot to do! So, let’s get started.

Yes, you read it right. It takes about 5 minutes to get the bare minimum set up to start coding your desktop application with electron

Okay, enough with the torturing. Let’s get started already.

Repo — https://github.com/anuj070894/electron_desktop_1

So, the most fundamental question that came to me when I first heard about electron is What is this electron thing?

  • So, Electron is platform for writing desktop apps using the patterns that is quite similar to how we write web applications

We have converted desktop apps to web apps?

What does this mean? Let’s see…

As most of you know that there is a hidden complexity with the web applications and it is that one can’t access the user’s hard drive. And we are only limited to executing the applications in the context of the browser. For some reasons, we can say it’s good for security reasons. And you all know why? So many defected softwares can so easily access our system and corrupt it if we let web accessing our system.

So, Electron is one that allows us to make websites(Yeah! You heard it right but not exactly) that can still lets us access the operating system stuffs.

The next question is How does it work then?

Electron === Google Chrome

Whatttttt????

Yeah. Pretty much how the inner gears work. Not how we write code though.

If you open up google chrome and check out the activity monitor that you will see a main process(the actual browser window) and then there are many child processes(the individual tabs). And all these processes are communicating through what we call as IPC(Inter Process Communication)

The reason that they architected in such a way is because this allowed to have better encapsulation of each tab and also for a better security end point. (Tabs not messing with each other)

In short, Renderer Processes are the child process and chrome app is the one main process that controls overall application.

Similarly, electron works. One is the main process(usually called as the Main Window) and there are many renderer processes.

These processes takes the help of IPC to communicate with each other. We will see soon how it actually works.

We are almost ready to dive into electron. But before we do that, let’s see the history of electron. Because then we will be able to say it is what it is!

Why websites for desktop apps?

Github -> Electron -> Atom

Github’s though process behind this

  • A lot of us use github for code review and management
  • Github want to be involved in the code writing process, too
  • Github thought that to be involved in code writing, why not write a code editor?
  • And most of the people write javascript. Do not believe me. Check http://githut.info/
  • So, let’s write our code editor in javascript
  • A javascript based code editor. And javascript is the world of people who can create anything in NO TIME. EXTENSIBLE
  • So, github saw lots of benefits to using web technology for desktop applications. And the github open sourced it
  • Check out this long list of apps that are using electron now. One such app is Slack. ❤

So, OKAYYYYY. Got it. Enough already.

Show me the code

Application 1

Create an application which shows a page where we can select a video(button) from the desktop and when we click Get Length(button) it displays the duration of the video — Your video xyz.mp4 is 20 seconds long

Steps —

  • Initial Steps

mkdir videoinfo

cd videoinfo

npm init with the defaults (To know more — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-1-a3c1431f1e15)

npm install --save electron

  • in index.js
const electron = require('electron');const {app} = electron; // this is sorta overall process(Electron App)app.on('ready', () => {    // event based    console.log('App is now ready!!!');});// the above listener that is attached can be broken down to three -// app - thing we are listening to// ready - event we are listening for// function to call when event occurs

To execute this —

in package.json

"scripts": {    "electron": "electron ."}

Run npm run electron and you should see something like below —

You should see that icon — third from right popping out

Let’s load a view and then we will discuss how it all comes together to form a desktop application

In index.html

<!DOCTYPE html><html>    <head>        <meta charset="utf-8">        <title>Video Info</title>    </head>    <body>        <h1>Video Info App</h1>    </body></html>

To load this view into our app, we de-structure BrowserWindow from electron and load this html file when the app is ready.

in index.js

const electron = require('electron');const {app, BrowserWindow} = electron; // this is sorta overall process(Electron App)let mainWindow;app.on('ready', () => {    // event based    mainWindow = new BrowserWindow({});    mainWindow.loadURL(`file://${__dirname}/index.html`); // this could be any url.});// the above listener that is attached can be broken down to three -// app - thing we are listening to// ready - event we are listening for// function to occur when event occurs

Now that we have come up a long way. Let’s discuss what all things has happened to have a clear picture.

When we run electron .at terminal our, the app is sorta overall main process that boots up and when it is ready creates the Main Window(Browser Window) and opens it.

The index.jsis the main process. As, you can see that index.html is loaded when the app boots up. This index.html could be any front end related technology — react, angular, vue, backbone, etc…

We will see it with react in the later parts.

Debugging

We can debug our electron apps just like we can debug any browser based application. View -> Toggle Developer Tools

Hoorayyy! We have built our first electron based desktop application. NOT YET! This is not what we discussed. But we are at a good state.

At this point, we should discuss about selecting videos from user’s hard drive

  • if we are reading information off the user’s file, can we do it via just the browser(index.html) or do we need electron(index.js) for us to do that?
  • Web page can get details about files that a user purposefully feeds into it, e.g., like an input element, i.e., web page opens a file picker
  • Electron, however, can read any arbitrary file off machine at any time
  • For our case, we can only use our vanilla javascript

in index.html

<!DOCTYPE html><html><head><meta charset="utf-8"><title>Video Info</title></head><body><h1>Video Info App</h1><form><input type="file" name="Choose a video:" accept="video/*"><button type="submit">Get length</button></form><script type="text/javascript">document.querySelector('form').addEventListener('submit', function (event) {event.preventDefault();console.log(document.querySelector('input').files); // output in image below});</script></body></html>

So, we have name, path, size, etc…but not the length of the video. So, How are we gonna do that?

Electron to the rescue

However, before we do that we will talk about a npm module fluent-ffmpeg that exposes some apis and makes working with ffmpeg easier from nodeJS and over ffmpeg cli to give lots of functionalities to convert videos, get metadata, etc… At the end of the day, electron . acts like a node application.

We first need to install the command line tools for ffmpeg , make sure you have brew installed on your system(https://brew.sh/)

which brew

brew install ffmpeg

which ffmpeg should show something like — /usr/local/bin/ffmpeg

To install it on windows —

https://github.com/adaptlearning/adapt_authoring/wiki/Installing-FFmpeg

To install —

npm install --save fluent-ffmpeg

All we need to do is require the ffmpeg in the browser and it should do the trick. BEEP… NOT GONNA WORK…

What we want to achieve?

  • User selects a file
  • Feed file details to ffmpeg
  • ffmpeg reads video file duration
  • show duration to user

But, where are gonna put this logic?

  • electron(index.js) — Electron specific configuration and logic — file access, operating specific, …
  • web app(index.html) — keep as generic as possible. Increase possible reuse on plain web

We have got file from web side. But we need to communicate it to electron(index.js) side of things. We have both the electron and web app part up and running and no communication is happening between them

If we can achieve something like shown in the diagram above, then we are good. We bind to the assumptions that we made earlier.

To do this, we need to make use of IPC System

THE BIG QUESTION — But does require works in electron?

Yes, it does. How?

Node(access to CommonJS(require) module system and also access to a lot of in-built modules like fs, path, etc.) + A web page(browser) = MainWindow

Thin of the equation above and let me know in the comments if you can figure out the maths ❤

We could have put our logic in index.html but to keep it separate concerns we are gonna put it in index.js , the electron side.

IPC Communication

in index.html

const electron = require('electron');
const {ipcRenderer} = electron;
document.querySelector('form').addEventListener('submit', (event) => {
event.preventDefault();
const { path } = document.querySelector('input').files[0];
ipcRenderer.send('video:submit', path); // (eventName, data that we want to send) - eventName in the form a colon based system. (name of the thing you are dealing with:verb) - video:submit. electron app has to be set up to receive this message as well.
});
ipcRenderer.on('video:metadata', (event, duration) => {
document.querySelector('#result').innerHTML = `Video is ${duration} seconds`;
});

in index.js

ipcMain.on('video:submit', (event, path) => { // event is the path sent from whom and has some information about it. data which is sent from the MainWindow
ffmpeg.ffprobe(path, (err, metadata) => {
// some very important data available in the metadata from ffprobe
// metadata.format.duration
mainWindow.webContents.send('video:metadata', metadata.format.duration);
});
});
// we probably have to re-start the application when you add new electron code

Branch — 01_Init — Switch to this branch in the code repo to check the code

This concludes our part 1 of Building desktop apps with electron. Hopefully, you have found it useful. Just to recap —

In this part, we discussed —

  • Electron — basics and history
  • IPC
  • ffmpeg

See you in part 2. Stay tuned. Will be publishing the entire series by this week :)

More where this came from

This story is published in Noteworthy, where thousands come every day to learn about the people & ideas shaping the products we love.

Follow our publication to see more product & design stories featured by the Journal team.

--

--

Anuj Baranwal

Full Stack Web Developer @AdobeSystems Bangalore. Sometimes I code, I draw, I play, I edit and write