Electron + React + Vite + Typescript
Published: 2023-02-11 18:48:49

> ## What is React ⚛️
React is a JavaScript library developed by Facebook which, among other things, was used to build Instagram.com. Its aim is to allow developers to easily create fast user interfaces for websites and applications alike. The main concept of React. js is virtual DOM

<br/>
> ## What is Electron
Electron.js is a runtime framework that allows the user to create desktop-suite applications with HTML5, CSS, and JavaScript. It’s an open source project started by Cheng Zhao, an engineer at GitHub.

<br/>
> ## What is Vite ⚡
Vite is a build tool created by Evan You, the creator of Vue. It allows for faster development thanks to super fast Hot Module Reload (HMR), fast cold start times, and CSS + JSX + TypeScript support out of the box.

## How to merge them together
At first we will initialize a new vite app using
- yarn `yarn create vite`
- npm `npm create vite`

Now answer the questions
you will get something like this
![Terminal Output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rxg7s2que5o3o7rire6i.png)

Now `cd` into the new directory and install the dependencies for me i will use
`cd vite-project && npm install`
- Optional add `sass` support using `npm i --save-dev sass` and vite will automatically detect it

Right now we have a functional react project
you can test it using `npm run dev`

### Add electron
First run `npm i --save-dev electron vite-electron-plugin`

and create a directory named `src-electron`
and create file `main.ts` inside it with the following code 
```ts
import { app, BrowserWindow, shell, ipcMain } from "electron";
import { release } from "node:os";
import { join } from "node:path";

// Disable GPU Acceleration for Windows 7
if (release().startsWith("6.1")) app.disableHardwareAcceleration();

// Set application name for Windows 10+ notifications
if (process.platform === "win32") app.setAppUserModelId(app.getName());

if (!app.requestSingleInstanceLock()) {
  app.quit();
  process.exit(0);
}

let win: BrowserWindow | null = null;
// Here, you can also use other preload
const url = process.env.VITE_DEV_SERVER_URL;
const DIST = join(__dirname, "..", "dist");
const indexHtml = join(DIST, "index.html");
const isDev = !app.isPackaged;

// Save userData in separate folders for each environment.
// Thanks to this you can use production and development versions of the app
// on same machine like those are two separate apps.
if (isDev) {
  const userDataPath = app.getPath("userData");
  app.setPath("userData", `${userDataPath}(dev)`);
}

async function createWindow() {
  win = new BrowserWindow({
    title: "Main window",
  });

  if (isDev) {
    win.loadURL(url);
    // Open devTool if the app is not packaged
    win.webContents.openDevTools();
    return;
  }
  // If not dev load html file
  win.loadFile(indexHtml);
}

app.whenReady().then(createWindow);

app.on("window-all-closed", () => {
  win = null;
  if (process.platform !== "darwin") app.quit();
});

app.on("second-instance", () => {
  if (win) {
    // Focus on the main window if the user tried to open another
    if (win.isMinimized()) win.restore();
    win.focus();
  }
});

app.on("activate", () => {
  const allWindows = BrowserWindow.getAllWindows();
  if (allWindows.length) {
    allWindows[0].focus();
  } else {
    createWindow();
  }
});

```

Familiar Vite React application structure, just with `src-electron` folder on the top :wink:  
*Files in this folder will be separated from your React application and built into `dist-electron`*  
```tree
├── src-electron                 Electron-related code
│   ├── main.ts                  Main-process source code
│
├── public                       Static assets
└── src                          Renderer source code, your React application
```
And now we will tell vite to compile our electron code by updating `vite.config.ts` to look like this


```ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import electron from "vite-electron-plugin";
import { rmSync } from "node:fs";

// Remove previously compiled electron to prevent code from conflicting
rmSync("dist-electron", { recursive: true, force: true });


// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    electron({
      // Include our electron code
      include: ["src-electron"],
    }),
  ],
});

```
We have two steps left to have every thing working
Update the package.json to include compiled electron code 
```json
{
  "name": "vite-project",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "main": "dist-electron/main.js", <-- The new line
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/react": "^18.0.27",
    "@types/react-dom": "^18.0.10",
    "@vitejs/plugin-react": "^3.1.0",
    "electron": "^23.0.0",
    "typescript": "^4.9.3",
    "vite": "^4.1.0",
    "vite-electron-plugin": "^0.7.4"
  }
}
```

Now run `npm run dev` this will start react server
and compile our electron code and start electron.
Running `npm run dev` will now give you an error saying that `"type":"module"` is not supported
so we will remove `"type":"module"` from our `package.json` and re run the command and we will have our electron app running

> If you want to know how to add nodeIntegration or How to use electron builder with this setup request from me and hopefully I will create a new post for each one because they will need more code and dependencies