メインプロセスとレンダラープロセス
Electron アプリを作成するときは、メインプロセスとレンダラープロセスを意識して使い分ける必要があります。

レンダラープロセス側で呼び出し可能な Electron モジュール(他の Node モジュールも含む)は制限されていて、実行できる JavaScript ライブラリは、Web ブラウザ上で実行可能な JavaScript に毛が生えたものくらいものと考えておくのがよいです。
ipcRenderer
モジュールは例外的にレンダラープロセスから使ってもよいとされているモジュールのひとつで、これ経由でメインプロセスに対して要求(メッセージ)を送ることができます。
逆にメインプロセスからのメッセージをハンドルすることもできます。
通知先のレンダラープロセスの指定
メインプロセスに対して、レンダラープロセスは複数存在することがあるので、メインプロセスからメッセージを送るときは、どのレンダラープロセスへのメッセージなのかを意識する必要があります。
レンダラープロセスからのメッセージに応答する
レンダラープロセスからのイベントを ipcMain.on()
でハンドルする場合、コールバック関数の第1パラメータとして渡される event: Electron.IpcMainEvent
オブジェクトから送信元のレンダラープロセス (sender: Electron.WebContents
) を参照することができます。
下記のメインプロセスは、my-add
イベントとしてレンダラープロセスから 2 つの数値を受け取り、IpcMainEvent.reply()
を使って送信元のレンダラープロセスに応答メッセージ(数値を足した結果)を返しています。
// レンダラープロセスからメッセージを受信して、応答メッセージを返す
ipcMain.on('my-add', (evt: Electron.IpcMainEvent, num1: number, num2: number) => {
evt.reply('my-add-reply', num1 + num2);
//evt.sender.send('my-add-reply', num1 + num2);
});
レンダラープロセス側では、ipcRenderer.send()
でメインプロセスにメッセージを送り、その応答を ipcRenderer.on()
でハンドルするように実装します。
import { ipcRenderer } from 'electron';
// メインプロセスへメッセージを送信
ipcRenderer.send('my-add', 100, 200);
// メインプロセスからメッセージを受信
ipcRenderer.on('my-add-reply', (evt: Electron.Event, result: number) => {
alert(result); //=> 300
});
ある BrowserWindow のレンダラープロセスにメッセージを送る
BrowserWindow
のインスタンスがあれば、そのウィンドウのレンダラープロセスに対してメッセージを送ることができます。
const win = new BrowserWindow(options);
win.webContents.once('did-finish-load', () => {
win.webContents.send('message-from-main', 'Hello!');
});
win.loadFile('public/index.html');
メインプロセス側から能動的にメッセージを送る場合は、レンダラープロセス側のコンテンツが準備できてから送らないといけないことに注意してください。 上記の例では、レンダラープロセスから最初に did-finish-load イベント を受診したときに、メッセージを送信するようにしています。
別の方法として、win.loadFile()
が返す Promise
が resolve 状態になるのを待つという方法があります。
タイミングは did-finish-load
イベントが発行されるタイミングと同じになります。
このあたりは、loadFile() の API ドキュメント に記述されています。
win.loadFile('public/index.html').then(() => {
win.webContents.send('message-from-main', 'Hello!');
});
レンダラープロセス側は、単純に ipcRenderer.on()
で受診すれば OK です。
import { ipcRenderer } from 'electron';
ipcRenderer.on('message-from-main', (evt: Electron.Event, msg: string) => {
alert('Message from main: ' + msg);
});