Vite + Vue3 + Electron + PixiJS でIPC通信

# はじめに
Vite + Vue3 + Electron + PixiJS の組み合わせを[前回](https://qiita.com/kaluna/items/a0180d08980515912103)作りましたが、それをベースに今回はそこからIPC通信を使って、Electronのメインプロセスと、Vue3のレンダラープロセスのデータの送受信を行っていきたいとおもいます
# 目次
1. [環境](#1-環境)
1. [electron-vite の通信の考え方](#2-electron-vite-の通信の考え方)
1. [send / on を使った送受信](#3-send--on-を使った送受信)
1. [invoke / handle を使った送受信](#4-invoke--handle-を使った送受信)
1. [参考](#5-参考)
# 1. 環境
- WebStorm 2023.3.2
- Node 18.18.2
- Vue 3.4.5
- Vite 5.0.11
- PixiJS 7.3.3
- Windows 11 Home
# 2. electron-vite の通信の考え方
[electron-viteサイト](https://electron-vite.org/) > `Guide` > `Development` > [Using Preload Scripts](https://electron-vite.org/guide/dev#using-preload-scripts) の図を見てみると、基本的には一般的なElectronと同じ構成になっていて、以下の２つのプロセスに分かれます
<dl>
<dt>Main Process</dt>
<dd>Electronの設定やNodeJSなど、サーバ的な役割</dd>
<dt>Renderer Process (Browser Window)</dt>
<dd>Vue3やPixiJSなどのブラウザ的な役割</dd>
</dl>

IPC通信をするのは、この`Main Process`と`Renderer Process` > `preload.js` が行い、`preload.js` は`contextBridge` を使って、`Renderer Process`内のスクリプトにデータを送ります

# 3. send / on を使った送受信
IPC通信でのデータの送受信には、`send`と`on`が使えます
## 3-1. Renderer Process -> Main Process 
まずは、ブラウザ側からElectron側にデータを送ります
### Renderer Process（ブラウザ）側
```vue:src/renderer/src/App.vue
<script setup lang="ts">
import PixiComponent from './components/PixiComponent.vue'
import { onMounted } from 'vue'
onMounted(() => {
  window.electron.ipcRenderer.send('call-main',{message:'call'})  /* Main Process に送信 */
})
</script>
```
### Main Process（Electron）側
```typescript:src/main/index.ts
import { app, shell, BrowserWindow, ipcMain} from 'electron'  //<-- ipcMainを追加
/* 省略 */
ipcMain.on('call-main',(_e,args) => {
  console.log(args.message)  //<-- callと表示されます
})
```
## 3-2. Main Process -> Renderer Process
次に、Electron側からブラウザ側にデータを送ります
### Main Process（Electron）側
```typescript:src/main/index.ts
let mainWindow: BrowserWindow  //<-- 他の関数でもアクセスできるように定義
function createWindow(): void {
  mainWindow = new BrowserWindow({...}  //<-- constを外します
}
/* 省略 */
ipcMain.on('call-main',(_e,args) => {
  console.log(args.message)
  mainWindow.webContents.send('response-renderer', { message: 'response' })  /* Renderer Process に送信 */
})
```
### Renderer Process（ブラウザ）側
```vue:src/renderer/src/App.vue
<script setup lang="ts">
import PixiComponent from './components/PixiComponent.vue'
import { onMounted } from 'vue'
onMounted(() => {
  window.electron.ipcRenderer.on('response-renderer', (_e, args) => {
    console.log(args.message)  /* responseと表示されます */
  })
  window.electron.ipcRenderer.send('call-main', { message:'call' })
})
</script>
```
`send / on` でのデータの送受信の書き方は、`Main Process`、`Renderer Process`ともに、基本的な書き方は同じです
# 4. invoke / handle を使った送受信
先ほどの`send / on` でのデータの送受信以外に、`invoke / handle` を使った書き方があります
## 4-1. Renderer Process -> Main Process
ブラウザ側からElectron側にデータを送ります
### Renderer Process（ブラウザ）側
```vue:src/renderer/src/App.vue
<script setup lang="ts">
import PixiComponent from './components/PixiComponent.vue'
import { onMounted } from 'vue'
onMounted( async () => {  //asyncを追加します
  await window.electron.ipcRenderer.invoke('call-main',{message:'call'})  /* Main Process に送信 */
})
</script>
```
### Main Process（Electron）側
```typescript:src/main/index.ts
import { app, shell, BrowserWindow, ipcMain} from 'electron'  //<-- ipcMainを追加
/* 省略 */
ipcMain.handle('call-main',(_e,args) => {
  console.log(args.message)  //<-- callと表示されます
})
```
## 4-2. Main Process -> Renderer Process
### Main Process（Electron）側
```typescript:src/main/index.ts
import { app, shell, BrowserWindow, ipcMain} from 'electron'
/* 省略 */
ipcMain.handle('call-main',(_e,args) => {
  console.log(args.message)
  return { message: 'response' }  //<-- Renderer Processに送信
})
```
### Renderer Process（ブラウザ）側
```vue:src/renderer/src/App.vue
<script setup lang="ts">
import PixiComponent from './components/PixiComponent.vue'
import { onMounted } from 'vue'
onMounted( async () => {
  const result = await window.electron.ipcRenderer.invoke('call-main',{message:'call'})  /* result に戻り値を受け取る */
  console.log(result.message)  /* response と表示されます */
})
</script>
```
# 5. 参考
- [Using Preload Scripts](https://electron-vite.org/guide/dev#using-preload-scripts)
- [おまけ｜IPCによるプロセス間通信( invoke, handleを利用 )](https://www.wakuwakubank.com/posts/773-electron-ipc/#index_id8)
- [Electron + React + Typescript プロセス間通信](https://zenn.dev/byebyeworld/articles/electron-react-data-send)
- [[Electron] IPC には新しい ipcRenderer.invoke() メソッドを使ったほうが便利 (v7+)](https://qiita.com/jrsyo/items/abe19dff2d950132d9cd)