Postmortem of an Electron App

After recently building a cross-platform Electron desktop app called DockJS, I’d like to share what went well, what didn’t go well, and how I solved particular technical problems along the way. By reflecting on this project, I hope to shed some light on what’s worth keeping in mind with any Electron project.

Ryan Westlake and I are both students at Turing: School of Software & Design. We have been consistently studying the fundamentals of JavaScript for the duration of this 7-month program, and are about to finish. Ryan and I are both motivated to learn more and more Javascript each day, to refine our craft, and hone our innovative capacity by advancing through a deeper understanding of our JavaScript’s core fundamentals.

One of the best methods of learning fundamentals along the way — we’ve found — is using the console in the browser or node’s REPL in the terminal. But there are some other alternatives that make writing longer functions and playing around much easier.

ScratchJS has always been a great go-to since its release for an extension for Chrome, and I was quite elated to see a much better alternative. Still, we wanted to access a REPL offline from our desktop, and add a few features that take practicing, writing, and learning JavaScript to another level.

With DockJS, we designed an interpretation of a traditional desktop application using Electron, specifically a JavaScript REPL interface that fully functions offline and can be accessed in the dock in multiple platforms.

Deciding to build this app posed a definite risk, as our timeframe was one week and we really had no idea to what lengths we would go to be production-ready, especially having no experience with Electron. To our surprise, evaluating code within the input field was pretty simple, even with a step in the middle of using babel as a transpiler:

$runButton.on('click', () => {
const code = transpileToES5()
eval(code)
})

const transpileToES6 = (editorCode) => {
const transpileToES5 = () => {
const editorCode = editor.getValue()
const result = babel.transform(editorCode, {
presets: ['es2015']
})
const code = result.code
return code
}

We even found a library that quite easily transforms any vanilla JavaScript to es6/es7 — a sort of reverse-transpiler, called lebab:

const transpileToES6 = (editorCode) => {
const { code, warnings } = lebab.transform(editorCode, ['let', 'arrow', 'class', 'commonjs', 'default-param'])

return [code, warnings]
}

Indeed, implementing these features went well. We even had some time to add a few lines to reassign console.log to a few aliases to go with our theme of using a coffee mug icon to symbolize using DockJS as a daily ritual:

const brew = console.log.bind(console)
const pour = console.log.bind(console)
const run = console.log.bind(console)
The Logo for DockJS is a coffee mug.

If there has ever been a time where I have built an app and written more one-line executions for features in my career thus far, it was in this app. Fortunately, that allowed us to dive deeper into the CodeMirror library and implement some subtle add-on features that mostly come out of the box, including highlighting the active line, visually indicating a match for brackets, and auto-closing brackets to name a few.

CodeMirror is a versatile text editor implemented in JavaScript for the browser, specialized for writing code. If you use the Node REPL or inspect a web page and mess around in the console — that’s using CodeMirror.

Using Electron with this app has felt like a breeze technically— not something you usually say as a developer. Although the scale of this app was not overly extensive and the light bulb went on more than expected, I would argue Electron is one of the most enjoyable libraries I’ve used to build an app. The documentation isn’t bad to say the least.

If we were to continue working on this project we would definitely be happy adding more language modes, which amount to a pretty long list. This would appeal to a much wider audience, and add some breadth to any coder’s skills as they played around in the editor. Perhaps our app would have opened with a window instead of a menubar, which would have allowed a user to use CMD + TAB while navigating across applications. Using menubar was a design choice that made sense to us since you could access it in the menu dock at the top of the screen, allowing for one dropdown window as opposed to many being potentially opened.

const menubar = require('menubar')

const mb = menubar({
width: 950,
height: 600,
index: `file://${__dirname}/index.html`,
icon: './app/icons/blue-cup@2x.png'
})

The code above demonstrates the ease of configuring your initial application’s window, an initial step of building an Electron app. Clearly, the scope of our project was smaller than the average app, but I would venture to say any developer exploring the often unexplored, yet well-mapped terrains of Electron would be elated to experience an enjoyable build-process wrapped in beautiful intricacy, if I may.

Show your support

Clapping shows how much you appreciated kswhyte’s story.