To get an overview on how to startup your first Electron project, this blog post is a great way to start. We’re going to explain how to get your first Electron project up and running.
Why Electron
In this day and age searching for project related information can be a hassle. You are constantly bombarded with information, and hit by hype trains for frameworks and technologies that someone says are the best for your new app.
Sometimes you don’t know where to start.
This blog post is not going to be like that. That’s because we are biased towards the Electron framework.
Not because we don’t follow the latest trends, but because we want to help you reduce the white noise while searching for a solution.
The first question you ask yourself is which technology should I use to find that solution.
We assume that this question is already answered and you chose to go with Electron. Even though Electron has competitors it has stayed on the market for several years.
Benefits of using Electron
- High data security
- Accessibility
- High performance
- Simplified management
- Reusable framework
- Compatibility
- Interaction with with web UI/UX tools
That’s why it also has a lot of example projects and good documentation. It’s being maintained regularly, and a lot of projects have been completed using the framework.
Just with that info you know you’re heading in the right direction.
Let’s get an overview of our tech stack
Electron
Our main technology is, of course, Electron. Let’s imagine this is your first time getting to know its tech, and you want to familiarize yourself with the API by bootstrapping your first simple project. For the ones that want to know more, here’s the official Electron documentation.
React
As we know, Electron is a framework for creating native applications with web technologies like JavaScript, HTML, and CSS. In this blog post, we’re going to use React library for building the client version of our app. You can find out more in their official documentation.
Webpack
Since this will be a simple project we’re going to use webpack for bootstrapping it all together. Webpack is a powerful tool in building your applications and this is a great starting point. Again, here is their official documentation.
Other
For the sake of making a complete starting point for your project we’re going to be using other technologies such as:
TypeScript – to have type safe Javascript code
SCSS – for styling your app
Yarn – package manager
Babel – javascript compiler
Webpack, babel, and TypeScript setup
Electron development is essentially Node.js development. So, if you don’t have it on your machine go to this quick start guide and install it.
Then, create a custom project folder and run yarn init command in the root folder to initialise your package.json file. You will get a prompt for information, but when you get to the main part of the init setup just input the following line:
"main": "./dist/main.js"
This points out our main entry point of the electron project.
After the yarn setup, we’re going to install Electron, webpack and babel with a single command that you can paste in your terminal which is positioned in the root of your project:
yarn add -D electron --dev --exact
webpack webpack-cli@3.3.12 webpack-dev-server
babel-loader @babel/core @babel/preset-env
@babel/preset-react @babel/preset-typescript
Note: For the sake of this blog post and the errors that were happening (which may be fixed) we’re going to be using a specific version: webpack-cli@3.3.12.
Next, we need a tsconfig.json setup so create that file in the root of your project. When you do that you can put inside the file the following code:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": [
"dom",
"es2015",
"es2016",
"es2017"
],
"allowJs": true,
"jsx": "react",
"sourceMap": true,
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
}
}
Basically, tsconfig.json is specifying the root files and the compiler options required to compile the project. We’re not gonna go into details, but if you want to learn more about tsconfig you can check out the link.
Furthermore, we need to add a babel configuration. Create a babel.config.js in the root of your folder with the following code:
module.exports = {
plugins: ["@babel/plugin-transform-async-to-generator"],
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript'
]
}
Also, we’re not going into details with this file and if you want to learn more about the babel plugins and presets you can check out the following links:
Plugins
Presets
HTML app entry point
We need a html file which we will load in as an entry point for our Electron app on start. Create an index.html file in the root of your project with the following markdown:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Your new Electron App</title>
</head>
<body></body>
</html>
Electron Webpack config
To configure the webpack config for our Electron side of the application we need to create a file in our root folder named webpack.config.js. For that file you can use the following code:
const path = require('path');
module.exports = {
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
devtool: 'source-map',
entry: './electron/main.ts',
target: 'electron-main',
module: {
rules: [
{
test: /.(js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].js',
},
};
In this code snippet we can see that target is a specific environment that webpack will compile for. In our case we’ve named it electron-main. Also, the entry is actually the entry point of the electron app. In our example we’ve made an electron folder in the root folder with a file called main.ts that has the main application code.
Electron app
The main code for creating an instance of our Electron app is in the main.ts file and the source code of that file looks like this:
import { app, BrowserWindow } from 'electron';
import * as path from 'path';
import * as url from 'url';
let mainWindow: Electron.BrowserWindow | null;
function createWindow() {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
},
});
if (process.env.NODE_ENV === 'development') {
mainWindow.webContents.openDevTools();
mainWindow.loadURL(`https://decode.agency:4000`);
} else {
mainWindow.loadURL(
url.format({
pathname: path.join(__dirname, '../index.html'),
protocol: 'file:',
slashes: true
})
);
}
mainWindow.on('closed', () => {
mainWindow = null;
});
}
app.on('ready', createWindow);
app.allowRendererProcessReuse = true;
In this code snippet we can see that we use the createWindow function to make a browser window of the application.
Pay attention to the if else condition where if we run the application in a ‘development’ environment open the browsers’ devtools and load the localhost of the React application which webpack setup we will see in the next section.
Also, if we don’t run the ‘development’ environment we just load up the index.html file that we defined earlier.
React setup
The UI part of our app will be made with React library. For this part we’re going to do a similar config setup as for the Electron app.
First we will need to set up our library by installing it. Use this snippet and run it in your terminal positioned in the root of your project.
yarn add react react-dom @types/react @types/react-dom
Then we will set up our webpack config by creating a file in the root of our project named webpack.react.config.js. But first, we will need to install the html webpack plugin. Use your terminal again and run the following code command snippet:
yarn add -D html-webpack-plugin
Next, you can add the following code to our webpack.react.config.js file:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
resolve: {
extensions: ['.tsx', '.ts', '.js'],
mainFields: ['main', 'module', 'browser'],
},
entry: './src/index.tsx',
target: 'electron-renderer',
devtool: 'source-map',
module: {
rules: [
{
test: /.(js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
devServer: {
contentBase: path.join(__dirname, '../dist/renderer'),
historyApiFallback: true,
compress: true,
hot: true,
port: 4000,
publicPath: '/',
},
output: {
path: path.resolve(__dirname, '../dist/renderer'),
filename: 'js/[name].js',
publicPath: './',
},
plugins: [
new HtmlWebpackPlugin(),
],
};
For the last part of our UI we will need a simple .tsx file with our code for the grounds of our UI side of the app. You can create an src folder inside the root of your app and there you can create an index.tsx file as your main file for the UI part of the Electron app.
In the file you can put the following code:
import React from "react";
import ReactDom from "react-dom";
const mainElement = document.createElement("main");document.body.appendChild(mainElement);
const App = () => {
return (
<section>
<h1>Hi from a react app</h1>
</section>
);
};
ReactDom.render(<App />, mainElement);
Styling
As a final touch, you can add styling grounds for UI part of the application. To do that, first you can install the packages
yarn add -D sass-loader sass css-loader style-loader resolve-url-loader
Then your need to add a new rule (module → rules) into our webpack.react.config.js
{
test: /.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
"style-loader",
// Translates CSS into CommonJS
"css-loader",
// Needed package for resolving relative paths in url()
// needs to be before sass-loader in loading chain
// more info on https://github.com/webpack-contrib/sass-loader#problems-with-url
"resolve-url-loader",
// Compiles Sass to CSS
"sass-loader",
],
},
Next we’ll create our styling folder structure in src. You can do something like this:
scss
├── base
│ ├── _colors.scss
│ ├── _index.scss
│ └── _typography.scss
└── main.scss
Try and change the color of h1 to gray and test that our installed packages are working well and that babel compiles it correctly. Add the following code to the files respectively:
/ colors.scss
$gray: #888ea7;
// typography.scss
h1 {
color: $gray;
}
// index.scss
@import "colors";
@import "typography";
// main.sccs
@import "base/index";
Lastly, we’re going to import our main.scss styling file in index.tsx
import "./scss/main.scss";
Start your app
Once we’ve set up all the project architecture the last thing we need to do is to add our terminal commands to scripts part of our project package.json file.
"scripts": {
"dev:electron": "NODE_ENV=development webpack --config webpack.electron.config.js --mode development && electron .”,
"dev:react": "NODE_ENV=development webpack-dev-server --config webpack.react.config.js --mode development"
},
To run the app, you can run the said script commands in your terminal respectively.
yarn dev:react
yarn dev:electron
Conclusion
Every time you want to learn something new you try and search up information about new tech.
The goal of this article was to combine all the needed information for making a simple Electron app with React library. We compiled the needed information into a concrete application bootstrap without any finished libraries or products.
We’ve used a simple webpack to strap our project and I’m sure that made you dig deeper to learn more about webpack itself combined with babel.
Making our main.ts file was the main goal so you can use it as a jumping-off point for your own project.
We wanted to guide you through all the oversaturated information that you can find online.
The goal is to encourage you to get up and running with your first Electron app on top of which you can build and create new stuff and keep learning. So, great job and good luck with new features.
If you have any questions, or want to work with an experienced team, feel free to contact us at business@decode.agency