Convert a React app to a Desktop app with Electron

Go to your react project and install Electron:

sh
yarn add --dev electron @types/electron electron-packager

Rename React's webpack.config.js to webpack.react.config.js

Create a new file webpack.electron.config.js with:

./webpack.electron.config.js
const path = require("path"); const app_dir = __dirname + '/src'; const config = { mode: 'development', entry: app_dir + '/electron.ts', target: 'electron-main', output: { path: __dirname + '/dist', filename: 'electron-app.js', }, module: { rules: [{ test: /\.tsx?$/, loader: "ts-loader", exclude: /(node_modules|bower_components)/ }] }, resolve: { extensions: [".ts", ".tsx", ".js", ".jsx"] } }; module.exports = config;

Inside the src folder, add a file electron.ts:

ts
import { app, BrowserWindow } from 'electron'; import * as path from 'path'; import * as url from 'url'; let mainWindow: Electron.BrowserWindow | null; function isDev() { return process.argv[2] == '--dev'; } function createWindow() { mainWindow = new BrowserWindow({ width: 800, height: 600, // maxHeight:600, // maxWidth:600, // minHeight:400, // minWidth:400, // backgroundColor:'#7B435B' webPreferences: { nodeIntegration: true, }, }); if (isDev()) { mainWindow.loadURL(`http://localhost:8080`); // mainWindow.webContents.openDevTools() } 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.on("window-all-closed", () => { if (process.platform !== "darwin") { app.quit(); } }); app.on("activate", () => { // On macOS 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 (BrowserWindow.getAllWindows().length === 0) { createWindow(); } });

Then, update package.json with:

json
"scripts": { "clean": "rm -rf dist/*", "build": "webpack --config webpack.react.config.js", "dev": "webpack serve --config webpack.react.config.js", "dev:electron": "webpack --config webpack.electron.config.js --mode development && electron ./dist/electron-app.js --dev", "build:electron": "webpack --config webpack.electron.config.js", "deploy": "electron-packager ./dist app-name --overwrite --asar=false --platform=linux --arch=x64 --prune=true --out=release-builds", "deploy-macos": "electron-packager ./dist app-name --overwrite --asar=false --platform=darwin --arch=x64 --prune=true --out=release-builds" }

Run yarn build and yarn build:electron

Then open ./dist/index.html and replace:

html
<script defer src="/app.js"></script></body> with: <script defer src="./app.js"></script></body>

and create ./dist/package.json

json
{ "name": "app-name", "version": "0.1.0", "main": "electron-app.js" }

Then run yarn deploy and go to ./release-builds/app-name-linux-x64/ and run ./app-name or yarn deploy-macos and run the app at ./release-builds/app-name-darwin-x64/app-name.app/...

Full source code here