So you ‘re either a React developer dabbling into the world of electron, or your looking to extend the abilities of Electron. Either way, you’ve ended up here because you’ve asked yourself the same question that took me down the rabbit hole, “How can I use React inside Electron?”.
I’m not going to be making anything spectacular in this example. To be honest, I had trouble compiling my own Electron project with React, so I simplified everything down to this boilerplate template. In this example, we’re simply going to make React compile our basic project, then build our application distributions using Electron. The complete code for this example can be found here on GitHub.
Creating the Project
Before we can start building our electron application we first need to install a few dependencies and define our project structure. Firstly, create a new directory for your project and navigate inside, then run npm init
and fill out the prompts to create your project boilerplate.
mkdir reactron && cd reactron
npm init
Now we’re ready to start installing our dependencies like React and React DOM! We’re also installing path as a production dependency cause we will be using it in with Electron later.
npm install --save react react-dom path
I’m not going to go over the React code, that could take a very long time depending on how far we choose to go. So I’m going to assume you know the basics. If not, you can just copy the files in the ./src
directory from the GitHub repo and follow one of these tutorials if you’d like to learn more.
Webpack Setup
Now we need to compile our React project down into a single bundle, for this we will use Webpack.
npm install --save-dev webpack webpack-cli
We’re also going to need webpack loaders like babel, style loaders and html compilers, let’s install those and delve a little deeper into what they do.
npm install --save-dev babel-core@6 babel-loader@7 babel-preset-env@1 babel-preset-react@6
Babel is the loader responsible for parsing all our fancy new-age Javascript into the currently supported specification ES5.
- babel-core: Transforms your ES6 code into ES5.
- babel-loader: Webpack helper plugin to parse ES6 dependencies into ES5.
- babel-preset-env: Determines which transformations/plugins to use and polyfills.
- babel-preset-react: Presets for all React plugins.
npm install --save-dev css-loader style-loader html-webpack-plugin
- style-loader: Compiles the referenced css files in our React components and injects them into the build file.
- css-loader: Is the parser to help Webpack interpret and transform our CSS.
- html-webpack-plugin: Outputs a compiled html file with resources adn tags linked.
There’s going to be allot of dependencies building up now… don’t worry, it’s just because of Webpacks extensability. Let’s define our project structure and start coding our resources, your project should resemble something like the following;
Reactron
|- assets
...react-assets...
|- build
|- bundle.js
|- index.html
|- dist
...electron-build-files...
|- node_modules
...installed-modules...
|- src
|- index.js
|- index.html
|- index.css
|- package.json
|- main.js
|- webpack.config.js
Configuring Webpack
Now we’re ready to start configuring Webpack to bundle our React project and resources into our ./build
directory for Electron. To start, open webpack.config.js
and import the webpack, path and html-webpack-plugin
modules.
const webpack = require('webpack');
const path = require('path');
const HtmlWebPackPlugin = require("html-webpack-plugin");
HTML-Webpack-Plugin
The html-webpack-plugin will take care of compiling our entry index.html
file after webpack has done it's magic.
const htmlPlugin = new HtmlWebPackPlugin({
title: "Reactron",
template: "./src/index.html",
filename: "./index.html"
});
Then we will configure our html-webpack-plugin
. This will handle injecting resources and data into our ./src/index.html
template through the Webpack build process, outputting the compiled result along with the bundled Javascript into the output directory.
The Webpack Build Pipeline
Now we are finally ready to configure our Webpack build pipline. Below everything we just wrote, define the following;
module.exports = {
entry: './src/index.js',
target: 'electron-renderer',
output: {
path: path.resolve(__dirname, 'build'),
publicPath: './',
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: [
/node_modules/,
/.json?/
],
use: {
loader: 'babel-loader',
query: {
presets: ["env","react"]
}
}
}, {
test: /\.(s*)css$/,
use: ['style-loader','css-loader']
}
]
},
plugins:[
htmlPlugin
],
resolve: {
extensions: ['.js','.jsx']
}
}
I don’t want too delve deep into Webpack, but you can read the the official documentation and examples here if you’d like to explore it further. This code snippet is essentially telling Webpack where our entry file is, where we want to output, and using what modules and plugins.
Electron
We’ve now build our Electron renderer with React, bundled with Webpack, and now we’re ready to begin coding our Electron application to serve it all.
npm install --save-dev electron
Coding our Electron Application
Let’s open the ./main.js
file and copy in the following;
const { app, BrowserWindow } = require('electron');
const path = require('path');
let mainWindow = null;
function createWindow() {
mainWindow = new BrowserWindow({
width:600,
height:400
});
mainWindow.loadFile(path.resolve(__dirname,'build/index.html'));
mainWindow.on('closed', () => {
if (process.platform !== 'darwin') app.quit();
});
}
app.on('ready', createWindow);
This is the absolute minimum code to start an Electron application. We’re importing our modules path and the app and BrowserWindow components from electron, then defining an empty mainWindow reference and createWindow()
function before attaching it to the app.on(‘ready’)
event. Our createWindow
function is initializing a new BrowserWindow
, loading the ./build/index.html
file we compiled with Webpack earlier, and handling the mainWindow.on(‘closed’)
event.
Running the App
And that’s it! We can execute npm webpack --mode production
to compile and then npm electron .
to start our Electron application. Let’s complete our project by compiling everything into a distribution with electron-builder.
Electron Builder
npm install --save-dev electron-builder
The Build Property
The majority of our electron-builder configuration happens inside the build
property within our package.json
.
"build": {
"productName":"Reactron",
"appId":"com.reactron.app",
"directories": {
"buildResources":"build",
"output":"dist"
}
...
}
We’re defining our productName
which is self explanatory and the appId
which is typically a unique identifier like a URL on the web. The important property is the directories, here you’ll specify the buildResources
where Electron will find your bundled Webpack output, and the output setting which defines the directory to output the build.
"directories": {
...
},
"files": [
"**/*",
"build/**/*",
"node_modules/**/*"
]
Now we specify the files to scan and package into our application bundle and we’re ready to run!
node electron-builder
Top comments (0)