What is ElectronJS and what is it used for?
ElectronJS, often referred to simply as Electron, is an open-source framework for building cross-platform desktop applications using web technologies such as HTML, CSS, and JavaScript. It was initially developed by GitHub and has since gained widespread popularity in the software development community. Electron allows developers to create desktop applications for Windows, macOS, and Linux without having to learn platform-specific programming languages or frameworks.
Common examples of applications built with Electron
Common examples of desktop applications built with Electron include code editors like Visual Studio Code, communication apps like Slack, and streaming platforms like Spotify.
Running Examples with Electron Fiddle
Electron Fiddle is a sandbox app written with Electron and supported by Electron's maintainers. It is highly recommended installing it as a learning tool to experiment with Electron's APIs or to prototype features during development.
Fiddle also integrates nicely with electron's documentation. When browsing through examples in electron's tutorials, you'll frequently see an "Open in Electron Fiddle" button underneath a code block. If you have Fiddle installed, this button will open a fiddle.electronjs.org link that will automatically load the example into Fiddle, no copy-pasting required.
What you will need to begin with
First, navigate to the Prerequisites page, to see what you will need to install on your machine in order to begin with using ElectronJS.
The most important prerequisites to have are:
- Github
- (Optional) Visual Studio Code
- (Optional) Github Desktop
- NodeJS and NPM/NPX/NVM Installed
⚠️ CAUTION⚠️ Although you need Node.js installed locally to scaffold an Electron project, Electron does not use your system's Node.js installation to run its code. Instead, it comes bundled with its own Node.js runtime. This means that your end users do not need to install Node.js themselves as a prerequisite to running your app.
To check which version of Node.js is running in your app, you can access the global process.versions variable in the main process or preload script. You can also reference https://releases.electronjs.org/releases.json.
⚠️ AVOID WSL⚠️ If you are on a Windows machine, please do not use Windows Subsystem for Linux (WSL) when following this tutorial as you will run into issues when trying to execute the application.
Electron apps are scaffolded using npm
, with the package.json
file as an entry point. Start by creating a folder and initializing an npm package within it with npm init
.
mkdir my-electron-app && cd my-electron-app
npm init
mkdir my-electron-app && cd my-electron-app
yarn init
This command will prompt you to configure some fields in your package.json
. There are a few rules to follow for the purposes of this tutorial:
- entry point should be main.js (you will be creating that file soon).
- author, license, and description can be any value, but will be necessary for packaging later on.
Then, install Electron into your app's devDependencies, which is the list of external development-only package dependencies not required in production.
npm install electron --save-dev
yarn add electron --dev
Your package.json
file should look something like this after initializing your package and installing Electron. You should also now have a node_modules folder containing the Electron executable
, as well as a package-lock.json
lockfile that specifies the exact dependency versions to install.
package.json
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jane Doe",
"license": "MIT",
"devDependencies": {
"electron": "23.1.3"
}
}
The .gitignore
file specifies which files and directories to avoid tracking with Git. You should place a copy of GitHub's Node.js gitignore template into your project's root folder to avoid committing your project's node_modules
folder.
The main
script you defined in package.json
is the entry point of any Electron application. This script controls the main process, which runs in a Node.js
environment and is responsible for controlling your app's lifecycle, displaying native interfaces, performing privileged operations, and managing renderer processes.
Before creating your first Electron app, you will first use a trivial script to ensure your main process entry point is configured correctly. Create a main.js
file in the root
folder of your project with a single line of code:
main.js
console.log('Hello from Electron 👋')
Because Electron's main process is a Node.js
runtime, you can execute arbitrary Node.js
code with the electron command (you can even use it as a REPL). To execute this script, add electron .
to the start
command in the scripts field of your package.json
. This command will tell the Electron executable to look for the main script in the current directory and run it in dev mode.
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jane Doe",
"license": "MIT",
"devDependencies": {
"electron": "23.1.3"
}
}
npm
npm run start
yarn run start
Your terminal should print out Hello from Electron 👋
.
Congratulations, you have executed your first line of code in Electron! Next, you will learn how to create user interfaces with HTML
and load that into a native window.
In Electron, each window displays a web page that can be loaded either from a local HTML file
or a remote web address
. For this example, you will be loading in a local file. Start by creating a barebones web page in an index.html
file in the root
folder of your project:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<meta
http-equiv="X-Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<title>Hello from Electron renderer!</title>
</head>
<body>
<h1>Hello from Electron renderer!</h1>
<p>👋</p>
</body>
</html>
Now that you have a web page, you can load it into an Electron BrowserWindow. Replace the contents of your main.js
file with the following code.
main.js
const { app, BrowserWindow } = require('electron')
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
})
In the first line, we are importing two Electron modules with CommonJS module syntax:
- app, which controls your application's event lifecycle.
- BrowserWindow, which creates and manages app windows.
main.js (Lines 3-10)
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
})
Many of Electron's core modules are Node.js
event emitters that adhere to Node's asynchronous event-driven architecture. The app module is one of these emitters.
In Electron, BrowserWindows can only be created after the app module's ready
event is fired. You can wait for this event by using the app.whenReady()
API and calling createWindow()
once its promise is fulfilled.
At this point, running your Electron application's start
command should successfully open a window that displays your web page!
Each web page your app displays in a window will run in a separate process called a renderer process (or simply renderer for short). Renderer processes have access to the same JavaScript APIs and tooling you use for typical front-end web development, such as using webpack to bundle and minify your code or React to build your user interfaces.
Application windows behave differently on each operating system. Rather than enforce these conventions by default, Electron gives you the choice to implement them in your app code if you wish to follow them. You can implement basic window conventions by listening for events emitted by the app and BrowserWindow modules.
On Windows and Linux, closing all windows will generally quit an application entirely. To implement this patter in your Electron app, listen for the app module's window-all-closed
event, and call app.quit()
to exit your app if the user is not on macOS.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})