Open2

Electron + React + vite 入門メモ

knaka Tech-Blogknaka Tech-Blog

概要

  • いまさらですが、Electron アプリ作成に挑戦する内容です。
  • Electron + React 環境作成 メモになります。

[ 公開 2025/01/15 ]


構成

  • Electron
  • React
  • vite
  • typescript

関連


  • install
npx create-electron-app@latest my-app --template=vite-typescript

  • start
yarn start
  • build
yarn package
  • 出力先 win , appName: アプリ名称
  • out/appName-win32-x64/appName.exe
  • 出力サイズは200MB程 , zip圧縮すると 100MB程でした。

  • package.json
{
  "name": "electron_3",
  "productName": "electron_3",
  "version": "1.0.0",
  "description": "My Electron application description",
  "main": ".vite/build/main.js",
  "scripts": {
    "start": "electron-forge start",
    "package": "electron-forge package",
    "make": "electron-forge make",
    "publish": "electron-forge publish",
    "lint": "eslint --ext .ts,.tsx ."
  },
  "devDependencies": {
    "@electron-forge/cli": "^7.6.0",
    "@electron-forge/maker-deb": "^7.6.0",
    "@electron-forge/maker-rpm": "^7.6.0",
    "@electron-forge/maker-squirrel": "^7.6.0",
    "@electron-forge/maker-zip": "^7.6.0",
    "@electron-forge/plugin-auto-unpack-natives": "^7.6.0",
    "@electron-forge/plugin-fuses": "^7.6.0",
    "@electron-forge/plugin-vite": "^7.6.0",
    "@electron/fuses": "^1.8.0",
    "@typescript-eslint/eslint-plugin": "^5.0.0",
    "@typescript-eslint/parser": "^5.0.0",
    "electron": "33.3.1",
    "eslint": "^8.0.1",
    "eslint-plugin-import": "^2.25.0",
    "ts-node": "^10.0.0",
    "typescript": "~4.5.4",
    "vite": "^5.0.12"
  },
  "keywords": [],
  "author": {
    "name": "",
    "email": ""
  },
  "license": "MIT",
  "dependencies": {
    "axios": "^1.7.9",
    "electron-squirrel-startup": "^1.0.1",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "react-router-dom": "^6.21.2"
  }
}


ルーティング

  • react-router 追加しました。
  • HashRouter 使う例です

書いたコード


  • react/src/App.tsx
  • ルーティング設定
import { HashRouter, Link, Route, Routes } from 'react-router-dom';
import Home from './client/home';
import About from './client/about';

export default function App(){
  return(
  <div className="App">
    <HashRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        About
      </Routes>
    </HashRouter>
  </div>
  )
}

  • react/src/client/home.tsx
import { Link } from 'react-router-dom';

...

  return (
  <div className="container mx-auto my-2 px-8 bg-white">
      <h1 className="text-4xl text-gray-700 font-bold my-2"
      >home</h1>
      <hr />
      <Link to="/about">[ about ]</Link>
      <hr />
  </div>
  )

  • 見た目
  • [ about ] リンクおすと、 about 画面に移動できました。

knaka Tech-Blogknaka Tech-Blog

IPC ( プロセス間通信 )

  • front から、Electronバック側の通信できそうでした。

関連


書いたコード


  • react/src/main.ts
  • test-first-api 追加します。
  • ipcMain.handle で、登録できました。
const { app, BrowserWindow, ipcMain, dialog } = require('electron');

  ipcMain.handle('test-first-api', async (_e, _arg) => {
    console.log("#test-first-api");
    console.log("Arguments received:", _arg); // 引数を確認
    return "ret.test-first-api: " + _arg;
  });

....


  • react/src/preload.ts
  • ipcRenderer.invoke で、ipcMain.handle設定した関数を呼び出せるようです。
const { ipcRenderer, contextBridge } = require('electron');

....

contextBridge.exposeInMainWorld('mytest1api', {
  test1api: (a) => ipcRenderer.invoke('test-first-api', a),
});


  • front
  • react/src/client/home.tsx
  • preload.tsで登録した、mytest1api 実行できました。
  const testProc = async function(){
    const res = await window.mytest1api.test1api("test1");
    console.log(res);
  }

....
<button id="button" onClick={() => testProc()}>Open</button>