手把手教你搭建electron环境(react+ts)

888 阅读3分钟

前言

很早之前写了一篇手把手教你搭建electron+react+ts环境 最近,将整套架构进行升级

  1. 抛弃webpack,采用vite+react+ts为主的技术栈
  2. 优化ipc通信封装

完整源码地址 github.com/qqjay2017/r…

话不多说,直接开始

项目初始化

$ npm create vite@5

分别选择react和typescript,创建完之后就有一个全新的vite+react起始项目

安装依赖

npm install  cross-env electron electron-builder npm-run-all vitest -D

都安装最新版本就好了

项目改造

vite.config.ts

export default defineConfig({
  plugins: [react()],
  base:"./",
  build: {
    outDir: 'dist-react'
  },
  server: {
    port: 5123,
    strictPort:true
  }
})

分别修改web项目的base,静态资源输出文件夹,本地开发端口

src文件夹下

分别新建electronui文件夹,将原本src下面的所有文件都移动到ui文件夹下

index.html

 <script type="module" src="/src/ui/main.tsx"></script>

修改web的入口

src/electron/main.ts

import { app, BrowserWindow } from "electron";
// 引用模块文件需要手动添加js后缀
import {  isDev } from "./util.js";
import {  getUIPath } from "./pathResolver.js";


app.on("ready", () => {
  const mainWindow = new BrowserWindow({});
  
   if (isDev()) {
    mainWindow.loadURL("http://localhost:5123");
  } else {
    mainWindow.loadFile(getUIPath());
  }
});


src/electron/util.ts

export function isDev(): boolean {
  return process.env.NODE_ENV === "development";
}

src/electron/pathResolver.ts

import { app } from "electron";
import path from "path";

export function getUIPath() {
  return path.join(app.getAppPath(), "/dist-react/index.html");
}

src/electron/tsconfig.json

{
    "compilerOptions": {
        "types": [
            "../../types"
        ],
        "strict": true,
        "target": "ESNext",
        "module": "ESNext",
        "outDir": "../../dist-electron",
        "skipLibCheck": true,
        "moduleResolution": "bundler"
    },
}

.eslintrc.cjs

 module.exports = {
  root: true,
  env: { browser: true, es2020: true },
  extends: [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:react-hooks/recommended",
  ],
  ignorePatterns: [
    "dist",
    ".eslintrc.cjs",
    "src/electron/preload.cts",
    "dist-electron",
    "dist-react",
  ],
  parser: "@typescript-eslint/parser",
  plugins: ["react-refresh"],
  rules: {
    "react-refresh/only-export-components": [
      "warn",
      { allowConstantExport: true },
    ],
  },
};

/types.d.ts

根目录下面新建types.d.ts,作为全局的类型文件

/tsconfig.json

{
 "compilerOptions": {
   "types": [
     "./types"
   ],
   "target": "ESNext",
   "useDefineForClassFields": true,
   "lib": [
     "ES2020",
     "DOM",
     "DOM.Iterable"
   ],
   "module": "ESNext",
   "allowJs": false,
   "esModuleInterop": false,
   "allowSyntheticDefaultImports": true,
   "forceConsistentCasingInFileNames": true,
   "moduleResolution": "Node",
   "skipLibCheck": true,
   /* Bundler mode */
   "allowImportingTsExtensions": true,
   "resolveJsonModule": true,
   "isolatedModules": true,
   "noEmit": true,
   "jsx": "react-jsx",
   /* Linting */
   "strict": true,
   "noUnusedLocals": true,
   "noUnusedParameters": true,
   "noFallthroughCasesInSwitch": true
 },
 "include": [
   "src"
 ],
 "exclude": [
   "src/electron"
 ],
 "references": [
   {
     "path": "./tsconfig.node.json"
   }
 ]
}

package.json

添加开发环境的命令


{
 "main": "dist-electron/main.js",
 "scripts": {
    "postinstall": "electron-builder install-app-deps",
    "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 && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview",
    "transpile:electron": "tsc --project src/electron/tsconfig.json"
   
   
   }


}


main字段记得加

构建相关

electron-builder.json

{
    "appId": "com.n-z.electron",
    "extraResources": [
        "dist-electron/preload.cjs",
        "src/assets/**"
    ],
    "files": [
        "dist-electron",
        "dist-react"
    ],
    "icon": "./desktopIcon.png",
    "mac": {
        "target": "dmg"
    },
    "linux": {
        "target": "AppImage",
        "category": "Utility"
    },
    "win": {
        "target": [
            "portable",
            "msi"
        ]
    }
}

package.json


{

 "scripts": {
    "postinstall": "electron-builder install-app-deps",
    "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 && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "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",
    "test:e2e": "playwright test",
    "test:unit": "vitest src"
  },


}


完整的package.json

{
  "name": "electron-course",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "main": "dist-electron/main.js",
  "author": "huang",
  "description": "huang",
  "scripts": {
    "postinstall": "electron-builder install-app-deps",
    "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 && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "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",
    "test:e2e": "playwright test",
    "test:unit": "vitest src"
  },
  "dependencies": {
    "os-utils": "^0.0.14",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "recharts": "^2.12.7"
  },
  "devDependencies": {
    "@types/os-utils": "^0.0.4",
    "@types/react": "^18.2.66",
    "@types/react-dom": "^18.2.22",
    "@typescript-eslint/eslint-plugin": "^7.2.0",
    "@typescript-eslint/parser": "^7.2.0",
    "@vitejs/plugin-react": "^4.2.1",
    "cross-env": "^7.0.3",
    "electron": "^32.2.1",
    "electron-builder": "^25.1.8",
    "eslint": "^8.57.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.6",
    "npm-run-all": "^4.1.5",
    "typescript": "^5.2.2",
    "vite": "^5.2.0",
    "vitest": "^2.1.1"
  },
   "overrides": {
    "@jridgewell/gen-mapping": "0.3.5"
  }
}

当时@jridgewell/gen-mapping这个包出问题了,不知道啥时候修复 github.com/jridgewell/…

启动dev效果

image.png

打包成功

image.png

小技巧-设置electron代理

export ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"

下一篇预告

ipc通信优化