Boilerplate of A Desktop App With Electron & React/Typescript (For busy developers)
Hey busy developers! Looking for a quick and straightforward way to get started with Electron, React, and TypeScript? You're in the right place! In this article, I'll guide you through creating a boilerplate for a desktop app using these technologies.
Now, you might be thinking: "But I've never worked with Electron before, and I don't have time to read the documentation!" Don't worry—that's exactly why this tutorial exists. I've designed it to be as simple and streamlined as possible, so you can have your app up and running in no time.
It's important to note that this isn't the only way to set up an Electron app. However, it's one of the fastest methods, perfect for those short on time who just want to get things up and running quickly.
So, let's get started!
Before diving in, it's essential to understand the basic structure of an Electron app. Essentially, it's a web application embedded within a Chromium/Electron/Node.js framework. To help illustrate this, check out the image below, which shows the build process of an Electron app:
Let's start by creating a basic react app using create-react-app with the command
npx create-react-app ./ --template typescript
This will create an empty react app in the current directory.
Now let's install electron with the command
npm install electron
and then create a directory called electron with the following files:
- index.ts
- preload.ts
- tsconfig.json
- index.ts
The index.ts file is the entry point for Electron. It contains all the necessary instructions to start a basic Electron browser window and load the index.html file from the build folder. This file, in turn, loads all the bundles created by the build script of React-scripts. The content of the index.ts file includes inline comments that provide explanations for each step of the process.
Here is the code:
import { app, BrowserWindow } from 'electron';
import * as path from 'path';
let mainWindow: Electron.BrowserWindow | null;
function createWindow() {
// Create the browser window.electron
mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
});
// and load the index.html of the app.
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// Open the DevTools.
// mainWindow.webContents.openDevTools();
// Emitted when the window is closed.
mainWindow.on('closed', () => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
mainWindow.maximize();
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', () => {
createWindow();
});
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X it"s common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow();
}
});
2. preload.ts
You can use preload.ts
which will be loaded before other scripts run on the main page. This script will always have access to both electron APIs and node APIs(and also the browser APIs) no matter whether node integration is turned on or off.
Since the app that we are building is pretty basic, it will not have much content.
// All of nodeJS APIs are available in the preload process
// it has the same sanbox as chrome extension
window.addEventListener('DOMContentLoaded', () => {});
export {};
3. tsconfig.json
If you've worked with TypeScript before, you're probably familiar with the tsconfig.json file. For those who may not be familiar, tsconfig.json is a configuration file that allows you to specify the root-level files and compiler options needed to compile a TypeScript project. The presence of this file in a directory indicates that the directory is the root of a TypeScript project. You can find more information about tsconfig.json and its various properties in the TypeScript documentation.
In our case, the content should look like the following:
{
"compilerOptions": {
"module": "commonjs",
"noImplicitAny": true,
"sourceMap": true,
"outDir": "../build",
"baseUrl": ".",
"paths": {
"*": ["node_modules/*"]
}
},
"include": [
"**/*"
]
}
Now the last thing that we have to do is configure the scripts in package.json
exactly as the image at the beginning of this post describes it.
{
"scripts": {
"build:web": "PUBLIC_URL=./ react-scripts build",
"build:desktop": "tsc -p electron/tsconfig.json",
"start:desktop": "npm run build:web && npm run build:desktop && electron ./build/index.js",
}
}
Now that we have everything set up, we can run the command npm run start:desktop
and see that app is built in an electron frame.
And that's it, you have created a desktop app with Electron & React/Typescript.
Bonus
- Creating executables for all platforms (Windows, Linux, macOS) with electron-builder
There are multiple packages to use to create executables for an electron app. There are lots of tutorials online on how to use them but I found electron-builder quite easy to set up and to understand.
Let's start by adding the configurations in the package.json file. It's a build property added to the root of the JSON file.
"build": {
"extraMetadata": {
"homepage": "./",
"main": "build/index.js"
},
"productName": "my-app-name",
"appId": "my-app-id-or-version",
"files": [
"build/**/*",
"node_modules/**/*"
],
"mac": {
"category": "public.app-category.productivity",
"target": [
"dmg",
"zip"
],
"icon": "src/Assets/img/unix.icns"
},
"linux": {
"maintainer": "john@doe.com",
"target": [
"tar.gz",
"deb"
],
"icon": "src/Assets/img/unix.icns"
},
"win": {
"target": [
"zip",
"dir"
],
"icon": "src/Assets/img/windows.ico"
}
}
Now, let's add scripts to trigger the creation of the files for all operating systems
"prebuild:package": "npm run build:web && npm run build:desktop",
"build:package:windows": "npm run prebuild:package && electron-builder --win",
"build:package:linux": "npm run prebuild:package && electron-builder --linux",
"build:package:mac": "npm run prebuild:package && electron-builder --mac",
"build:package:all": "npm run prebuild:package && electron-builder --win --linux --mac"
And there you have it. I think the names of the scripts speak for themselves. No further explanation is needed.
2. Automatic updates of the electron app in production
Automatic updates of the electron app in production can also be achieved in many ways but the most popular one is doing it via an "update server". I think that one is subject to a whole new blog post that I will publish in the future if I have time.
References: