This project was bootstrapped with Create React App with --template typescript
option.
On the top of it, the following features have been added with relatively small changes:
- TypeScript supports for Electron main process source code
- Hot-reload support for Electron app
- Electron Builder support
Runs the Electron app in the development mode.
The Electron app will reload if you make edits in the electron
directory.
You will also see any lint errors in the console.
Builds the Electron app package for production to the dist
folder.
Your Electron app is ready to be distributed!
my-app/
├── package.json
│
## render process
├── tsconfig.json
├── public/
├── src/
│
## main process
├── electron/
│ ├── main.ts
│ └── tsconfig.json
│
## build output
├── build/
│ ├── index.html
│ ├── static/
│ │ ├── css/
│ │ └── js/
│ │
│ └── electron/
│ └── main.js
│
## distribution packages
└── dist/
├── mac/
│ └── my-app.app
└── my-app-0.1.0.dmg
npx create-react-app my-app --template typescript
cd my-app
yarn add @types/electron-devtools-installer electron-devtools-installer electron-is-dev electron-reload
yarn add -D concurrently electron electron-builder wait-on cross-env
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"sourceMap": true,
"strict": true,
"outDir": "../build", // Output transpiled files to build/electron/
"rootDir": "../",
"noEmitOnError": true,
"typeRoots": [
"node_modules/@types"
]
}
}
import { app, BrowserWindow } from 'electron';
import * as path from 'path';
import * as isDev from 'electron-is-dev';
import installExtension, { REACT_DEVELOPER_TOOLS } from "electron-devtools-installer";
let win: BrowserWindow | null = null;
function createWindow() {
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
if (isDev) {
win.loadURL('http://localhost:3000/index.html');
} else {
// 'build/index.html'
win.loadURL(`file://${__dirname}/../index.html`);
}
win.on('closed', () => win = null);
// Hot Reloading
if (isDev) {
// 'node_modules/.bin/electronPath'
require('electron-reload')(__dirname, {
electron: path.join(__dirname, '..', '..', 'node_modules', '.bin', 'electron'),
forceHardReset: true,
hardResetMethod: 'exit'
});
}
// DevTools
installExtension(REACT_DEVELOPER_TOOLS)
.then((name) => console.log(`Added Extension: ${name}`))
.catch((err) => console.log('An error occurred: ', err));
if (isDev) {
win.webContents.openDevTools();
}
}
app.on('ready', createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (win === null) {
createWindow();
}
});
"homepage": ".", # see https://create-react-app.dev/docs/deployment#serving-the-same-build-from-different-paths
"main": "build/electron/main.js",
"author": "Your Name",
"description": "React-TypeScript-Electron sample with Create React App and Electron Builder",
...
"build": {
"extends": null, # see https://github.com/electron-userland/electron-builder/issues/2030#issuecomment-386720420
"files": [
"build/**/*"
],
"directories": {
"buildResources": "assets" # change the resource directory from 'build' to 'assets'
}
},
"scripts": {
"postinstall": "electron-builder install-app-deps",
"electron:dev": "concurrently \"cross-env BROWSER=none yarn start\" \"wait-on http://127.0.0.1:3000 && tsc -p electron -w\" \"wait-on http://127.0.0.1:3000 && tsc -p electron && electron .\"",
"electron:build": "yarn build && tsc -p electron && electron-builder",