# Electron + Vite + Typescript + React -- 桌面應用開發 ep1. 環境設定
參考 [Electron Course - Code Desktop Applications (inc. React and Typescript)](https://www.youtube.com/watch?v=fP-371MN0Ck)
## Create project
建一個資料夾,並進入資料夾路徑
1. create vite project
```bash
npm create vite .
```
- 選 React

- 選 TypeScript

2. 所有檔案會出現長這樣

3. 安裝package.json的東西
```bash
npm install
```

4. 就會出現 node_modules,裡面就會一堆 dependencies,到這部就算是初步完成project的建置

5. 檢查是否可以跑出預設的介面
- 先下指令
```bash
npm run dev
```
- 會在預設的port長這樣

## 設定 React
1. 存放 code 的 `src/` 中新增一個 `ui/` 資料夾

2. 把預設的的檔案都放到 `ui/` 底下

3. 設定 ui 的 javascript 路徑,因為他剛剛被我移到 `ui/` 底下了

4. 測試一下目前做的對不對
```bash
npm run dev
```

5. 把 `vite` 的 icon圖片svg 還有不用的東西刪掉
- public 這裡可以整個刪掉

- 把有用到這張圖的地方也刪掉

- 就剩這樣

6. 設定 **包裝完的程式** 要放哪個路徑
- 首先看到他原本 build 完是直接丟在 `dist/` 底下
```bash
npm run build
```

- 為了跟 electron 的 build 出來的東西有區別,在 `vite.config.ts` 中設定 output 的路徑

- 在跑一次 build,他就會到我們指定的 `dist-react/` 中了,這時候 `dist/` 就可以刪掉了
```bash
npm run build
```

- 最後,記得把他加到 `.gitignore`,這樣他就不會被 push 上去了

## 設定 Electron
1. 安裝 electron
```bash
npm install --save-dev electron
```
2. 在 `src/` 底下創建 `electron/` ,並新增 `main.js`

3. `main.js`: 控制 electron 的介面,叫他載入 `dist-react/index.html`
```javascript
import {app, BrowserWindow} from 'electron';
import path from 'path';
app.on("ready", ()=>{
const mainWindow = new BrowserWindow({});
mainWindow.loadFile(path.join(app.getAppPath(), '/dist-react/index.html'))
})
```
4. 在 `package.json` 設定主要程式進入點,以及react和electron的執行腳本
```jsonld
{
...
"main": "src/electron/main",
"homepage": "./",
"scripts":{
"dev:react": "vite",
"dev:electron":"electron .",
...
}
}
```

5. 到 `vite.config.ts` 中設定路徑
- 加上 相對路徑的符號 `./`

- 否則build出來會長這樣,這樣會找不到檔案

6. 開始跑 electron 應用程式
```bash
npm run dev:electron
```

## 設定 TypeScript
1. 刪先看到這三個檔案
- `tsconfig.json`:全局的配置。
- `tsconfig.app.json`:前端的配置(React 项目)。
裡面加上這行表明 這個 TypeScript 專案是一个複合專案,允許引用其他项目
```jsonld
{
...
"composite": true,
...
}
```
- `tsconfig.node.json`:後端的配置(Node.js 或 Electron)。
裡面加上這行表明 這個 TypeScript 專案是一个複合專案,允許引用其他项目
```jsonld
{
...
"composite": true,
...
}
```

2. 在全局的 `tsconfig.json` 中指定 包含和不包含設定涵蓋的範圍

3. 在 `electron/` 底下新增 `tsconfig.json`,並把 `main.js` 改名為 `main.ts`

4. 在 `electron/tsconfig.json` 中
```javascript
{
"compilerOptions": {
// require strict types (null-save)
"strict": true,
// tell TypeScript to generate ESM Syntax
"target": "ESNext",
// tell TypeScript to require ESM Syntax as input (including .js file imports)
"module": "NodeNext",
// define where to put generated JS
"outDir": "../../dist-electron",
// ignore errors from dependencies
"skipLibCheck": true
}
}
```
5. 在 `package.json` 加入 `electron/tsconfig.json` 編譯
```jsonld
"scripts":{
...,
"transpile:electron": "tsc --project src/electron/tsconfig.json"
}
```
6. 執行 `build`,就會看到build完的東西跑到 `dist-electron/` 底下了
```bash
npm run transpile:electron
```

7. `package.json` 設定程式進入點為 `electron/main`,因為我們是要跑 electron 而不是 react
```jsonld
{
...
"main": "dist-electron/main.js",
...
}
```
8. 測試能不能跑
```bash
npm run dev:electron
```
應該要是依樣長這樣喔

9. 最後,記得加到 `.gitignore`,設定TypeScript到這就結束了

## 設定 electron-builder
1. 安裝 `electron-builder`
```bash
npm i --save-dev electron-builder
```
2. 設定要件成怎樣的 執行檔
- 創建 `electron-builder.json`

- 在 `electron-builder.json` 設定不同平台要創建的執行檔格式,`icon`的部分隨便,沒有設定應該就是預設的 icon
```jsonld
{
"appId": ".com.lun.ICDApp",
"files":["dist-electron", "dist-react"],
"icon": "desktopIcon.png",
"mac":{
"target":"dmg"
},
"linux":{
"target":"AppImage",
"category":"Utility"
},
"win":{
"target":["portable", "msi"]
}
}
```
3. 在 `package.json` 中設定生成執行檔的腳本
```jsonld
{
...,
"scripts":{
...,
"dist:mac": "npm run transpile:electron && npm run build && electron-builder --mac --arm64",
"dist:win": "npm run transpile:electron && npm run build && electron-builder --win --x64",
"dist:linux": "npm run transpile:electron && npm run build && electron-builder --linux --x64",
},
...
}
```
4. 看你用啥 OS,就執行哪個,阿我是 windows
```bash
npm run dist:win
```

5. 到產生執行檔的路徑 `dist/`

6. 長這樣就代表build的功能設定完成了!

## 設定開發模式和生產模式
1. 安裝 `corss-env`
```bash
npm i --save-dev cross-env
```
2. 到 `package.json` 設定辨別現在的模式是 development 在執行 electron
```jsonld
{
...,
"scripts":{
...,
"dev:electron": "cross-env NODE_ENV=development electron .",
},
...
}
```
3. 上面是OS 知道現在啥情況,但是程式碼並不知道,所以現在要寫一個程式來判斷現在是開發模式還是啥
- 先在 `src/electron/` 底下創建一個 `util.ts`

- 判斷函數 `isDev()`
```javascript
export function isDev(): boolean {
return process.env.NODE_ENV === 'development';
}
```
4. 在 `vite.config.ts` 設定 react 要跑在哪個 port,`port` 那個就看你自己可以隨便定

5. 先測試 react 是不是跑在 port 上
```
npm run dev:react
```
水 :laughing:

6. 對於 electron 到底要載哪個,介面也要設定,到 `src/electron/main.ts`
```javascript
import {app, BrowserWindow} from 'electron';
import path from 'path';
import { isDev } from './util.js';
app.on("ready", ()=>{
const mainWindow = new BrowserWindow({ });
if(isDev()){
// 如果是開發模式
mainWindow.loadURL('http://localhost:5173');
}else{
// 如果是生產模式
mainWindow.loadFile(path.join(app.getAppPath(), '/dist-react/index.html'))
}
})
```
7. 開始測試
要開兩個 terminal,順序沒差,如果沒開react server的話electron就開不了喔
- 一個執行 react 的 server
```bash
npm run dev:react
```
- 一個執行 electron 的應用程式
```bash
npm run dev:electron
```

## 優化開發
為了不用每次都要開兩個 terminal
1. 安裝 `npm-run-all`
```bash
npm i npm-run-all
```
2. `package.json` 修改執行腳本
```jsonld
{
...,
"scripts": {
"dev": "npm-run-all --parallel dev:react dev:electron", //加這行
"dev:react": "vite",
"dev:electron": "npm run transpile:electron && cross-env NODE_ENV=development electron .",//改這行
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview",
"transpile:electron": "tsc --project src/electron/tsconfig.json",
"dist:mac": "npm run transpile:electron && npm run build && electron-builder --mac --arm64",
"dist:win": "npm run transpile:electron && npm run build && electron-builder --win --x64",
"dist:linux": "npm run transpile:electron && npm run build && electron-builder --linux --x64"
},
}
```
3. 這樣之後開發就只要跑一行就行
```bash
npm run dev
```

4. `vite` 支持 HMR,所以就一邊改程式,畫面也會跟著變

可以開始開發app了!