The author selected the Apache Software Foundation to receive a donation as part of the Write for DOnations program.
Electron is an open source framework for creating native applications with web technologies like JavaScript, HTML, and CSS. It combines support for building and running applications cross platform on Mac, Windows, and Linux. Many popular desktop applications have been built using Electron, such as Visual Studio Code, WhatsApp, Twitch, Slack, and Figma.
Electron facilitates designing more complex application features like automatic updates or native menus, which means that developers can focus on the core design of their application. Further, Electron is an open source project maintained by GitHub with an active community of contributors.
In this tutorial, you’ll first set up a project and install Electron. After that you’ll create your first “Hello World!” application using Electron and customize it. You’ll implement graceful window setup and create new windows for the application. After following all of these steps, you will have an Electron cross-platform desktop application on macOS.
To complete this tutorial, you will need:
Note: This tutorial was tested on macOS 10.15.3.
First you’ll install Electron to your machine and create the project folder to build the desktop application.
To start the Electron installation process, create the project folder called hello-world
and navigate to the folder with the following commands:
- mkdir hello-world
- cd hello-world
Next, you’ll initiate your project by creating the package.json
file.
The package.json
file is an essential part of a Node.js application, it performs the following:
To create the package.json
file, run the following command:
- npm init
You will be asked a series of questions, starting with the package name. You can use the default application name, hello-world
, as your package name.
Then it asks for the version. To use v1.0.0, which comes as default, press ENTER
.
After that, it asks for a description. There you can add a description of your project, something like: hello world application on Electron.js
.
Next, for the entry point, enter main.js
.
The file invoked at the initial run time of application is known as the entry point. In this case, main.js
is the entry point of the package.json
file.
For the remaining questions, accept the defaults with ENTER
.
Note: In this tutorial we’re leaving the author and license empty, but you can use your first and last name as the author depending on your project status. The license of your package specifies how others are permitted to use the application, and any restrictions you’re placing on it. The most common licenses are: MIT, BSD-2-Clause, and ISC. For more details, check the full list of SPDX license IDs. From there you can use a preferred license for your project, but this is not mandatory.
Having followed the prompts you’ll receive the following output:
Output:. . .
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (hello-world)
version: (1.0.0)
description: hello world application on Electron.js
entry point: (index.js) main.js
test command:
git repository:
keywords:
author:
license: (ISC)
After that, you’ll be asked to confirm the configuration:
Output:About to write to /hello-world/package.json:
{
"name": "hello-world",
"version": "1.0.0",
"description": "hello world application on Electron.js",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Is this OK? (yes)
You’ll now have the newly generated package.json
file inside your hello-world
project directory. Next you’ll install Electron.
Now you’ll implement the configuration of the package.json
file and install Electron.
For that, open the package.json
file in your preferred text editor:
- nano package.json
Add the following highlighted line inside the scripts
object:
{
"name": "hello-world", "version": "1.0.0",
"description": "hello world application on Electron.js",
"main": "main.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
The scripts
property takes an object with as many key/value pairs as desired. Each one of the keys in these key/value pairs is the name of a command that can be run. The corresponding value of each key is the actual command that can be run. Scripts are frequently used for testing, building, and streamlining of the needed commands.
In this project, you’ll use start
as a key and electron .
as a value.
Once you’re done, save and exit the file.
Next, you’ll install Electron as a development dependency in your project. Run the following command inside your hello-world
project directory:
- npm install --save-dev electron
After successfully installing the Electron dependency to your project, the package.json
file will be similar to this:
{
"name": "hello-world",
"version": "1.0.0",
"description": "hello world application on Electron.js",
"main": "main.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "^8.2.1"
}
}
The dependency property takes an object that has the name and version for each dependency.
There are two dependency properties dependencies
and devDependencies
that can be identified with a key difference. The dependencies
property is used to define the dependencies that a module needs to run in production. The devDependencies
property is usually used to define the dependencies the module needs to run in development. To install the package as devDependencies
use the --save-dev
flag with your command.
You’ve installed Electron to your machine and created the project folder to build your application. Now you’ll write your first hello-world
application using the Electron framework.
Let’s start writing your first Electron application.
Electron operates with two types of processes: the main process (server-side) and the renderer process (client-side). The Electron main process is run on the Node.js runtime.
For that, you’ll be working with two files: main.js
and index.html
.
main.js
is your application’s main process and index.html
is your Electron application renderer process.
hello-world
+-- package.json
+-- main.js
+-- index.html
Next, we create a manual browser window and load the content using Electron API calls, which you can use to execute HTML, CSS, JavaScript, and so on.
First open your main.js
file:
- nano main.js
Then add the following line of code to implement the BrowserWindow
module:
const { app, BrowserWindow } = require('electron')
This contains two destructuring assignments called app
and BrowserWindow
, which are required for an Electron module. The Browserwindow
module is used to create a new window in your Electron application.
Next, add the following code to your main.js
file:
. . .
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600
})
mainWindow.loadFile('index.html')
}
app.whenReady().then(createWindow)
You add an Electron createWindow
function to your hello-world
application. In this function, you create a new BrowserWindow
renderer process and pass the width
and height
parameters. The width and height will set the application window size.
The mainWindow.loadFile()
method renders some contents into the BrowserWindow
. The index.html
file will load the content.
The main process will be started when the app.whenReady().then(windowName)
method is ready. At this point, the main process calls the createWindow
function. This function creates a new renderer process, or browser window instance, with a width of 800px and height of 600px. Then the renderer process proceeds to load content using mainWindow.loadFile('index.html')
method. In this tutorial, you use index.html
as the filename.
Next add the following events code to your file:
. . .
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
You add the two main system events into the project—window-all-closed
and activate
events:
window-all-closed
: Quits the application when all windows are closed. On macOS it is common for applications and their menu bar to stay active until the user quits explicitly with CMD
+Q
.activate
: Various actions can trigger this event, such as launching the application for the first time, attempting to re-launch the application when it’s already running, or clicking on the application’s dock (macOS) or taskbar icon.After adding these code blocks, your final output of the main.js
file will be similar to this:
const { app, BrowserWindow } = require('electron')
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600
})
mainWindow.loadFile('index.html')
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
Once you’re done, save and exit this file.
Next, create and open the index.html
file:
- nano index.html
Add the following code, which is sent as the final output:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body
<h1>Hello World!</h1>
</body>
</html>
Here you create a static HTML web page. The Electron application renderer process supports all HTML syntax since Electron uses Chromium for the rendering process.
Now that you’re done, you can run your application:
- npm start
You will get an application window as an output.
You’ve created your first cross-platform application with the Electron framework. Next you’ll work with some customizations, which you can add for interactivity.
Now you have completed the initial setup of your first cross-platform application using the Electron framework. Let’s see what else you can do to improve the native behavior of the application.
Electron has a number of built-in features such as dialog boxes, windows options, new windows, menus, shortcuts, notifications, touch bars, session controls, and so on, that improve the user experience of your desktop application. Let’s add some features to customize the hello-world
application.
When you load a page into the window directly, at the startup of your application you may see the page does not load at once. This isn’t a great experience in native applications. Let’s fix this issue in a few steps.
To do this, you need to hide the BrowserWindow
by passing new configuration parameters at the time it gets created.
For that, open the main.js
file:
- nano main.js
Add the show: false
parameter to the body of the BrowserWindow
object:
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
show: false
})
Next, you’ll add a new listener to the BrowserWindow
instance by adding the highlighted code line inside the createWindow
function body. You’ll also add new configuration parameters into the BrowserWindow
to change the background color of the initially built window.
For that, you have to add the following code line of backgroundColor
object, inside the BrowserWindow
function. Feel free to change the hex color code as you wish.
backgroundColor: '#Your hex color code'
Add this line like the following highlighted code to your createWindow
function:
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
show: false,
backgroundColor: '#ffff00'
})
mainWindow.loadFile('index.html')
mainWindow.once('ready-to-show', mainWindow.show)
}
To reduce the garbage collection, you need to execute this listener one time by using the once
keyword. Therefore, the mainWindow.show
method executes only once at the run time of this application.
Now save your file and run your application using the terminal:
- npm start
Your application will show with a yellow background.
Finally, you will see the application window loading gracefully.
The use of more than one window is a common feature of basic to advanced applications. Let’s add that feature to your newly created application.
Electron can create multiple renderer processes (multiple windows) from a single main process.
First, open main.js
:
- nano main.js
Create a new method called secWindow
and set the width
and height
parameters of the newly created window by adding the highlighted code:
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
show: false,
backgroundColor: '#ffff00'
})
const secWindow = new BrowserWindow({
width: 600,
height: 400,
})
. . .
}
Now load content to the newly created BrowserWindow
renderer process. At this time you’ll load some remote URL (Website) content.
In this tutorial, you’re using https://www.digitalocean.com
web content for the second window of the application. For that, in the second window initialization secWindow.loadURL
, you add the following code line to the body of the createWindow
function:
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
show: false,
backgroundColor: '#ffff00'
})
const secWindow = new BrowserWindow({
width: 600,
height: 400,
})
mainWindow.loadFile('index.html')
secWindow.loadURL('https://www.digitalocean.com/')
mainWindow.once('ready-to-show', mainWindow.show)
}
Now save and exit your file and run your application in the terminal:
- npm start
You will get your initial window with the yellow background and a new application with the loaded URL.
You’ve made customizations to your newly created application to make it more interactive for users. Now it’s time to build your Electron application.
After adding some features to your application, you need to build it for the purpose of distribution. In this section, you will learn how to build the application for various platforms.
The build process of the Electron application is considered somewhat hard because it needs a lot of tools. However, here you’ll use the electron-builder
CLI tool that provides the best way to build your application for any platform.
First, you’ll install the electron-builder
CLI tools globally. To do this run the following command:
- sudo npm install -g electron-builder
Note: You can use either npm
or yarn
to install electron-builder
—there are no noted differences in performance. If you intend to develop your application in the long term, the makers of electron-builder
recommend yarn
to avoid potential compatibility issues. To install using yarn
, you’ll need to ensure it’s installed on your computer and then run yarn add electron-builder --dev
to install electron-builder
with yarn
.
After completing the installation of the electron-builder
, you can verify the success of it by running the following command in your terminal:
- electron-builder --version
You’ll receive the current version of Electron in your output.
Now you can build your first cross-platform application. To do this open your terminal and run the following command in your project directory:
- electron-builder -mwl
You use the flags -mwl
to build applications for macOS, Windows, and Linux respectively.
Note: Only macOS users can build for all platforms. Windows users can build the application for Windows and Linux platforms only. Linux users can build only for Linux platforms. For more details, you can refer to the documentation.
To build applications for separate operating systems use the following:
Build applications for macOS
:
- electron-builder --mac
Build applications for Windows:
- electron-builder --win
Build applications for Linux
:
- electron-builder --linux
This process takes some time while dependencies download and your application builds.
Your project directory creates a new folder called dist
. All your built applications and unzip versions of the application are located in that folder.
As an example, if you build your application for all platforms, your project dist
folder is similar to the following file structure:
hello-world
+-- hello-world-1.0.0-mac.zip
+-- hello-world-1.0.0.dmg
+-- hello-world Setup 1.0.0.exe
+-- win-unpacked
+-- mac
+-- linux-unpacked
+-- hello-world_1.0.0_amd64.snap
electron-builder
builds the Electron app for the current platform and current architecture as the default target.
x64
will be the output. Otherwise if you build on Linux, the output will be Snap and AppImage files for the current architecture.You’ve now built your application for all platforms.
In this tutorial, you created your first cross-platform application with the Electron framework, added native features, and built it for distribution, on macOS.
To learn more about Electron, you can check out their documentation. Now you can also share your newly created desktop application with anyone by creating an installer.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!