remote

remoteモジュールは、レンダラープロセス(ウェブページ)とメインプロセス間でインタープロセスコミュニケーション(IPC)をする簡単な方法を提供します。

Electronでは、GUI関連モジュール(dialogmenuなど)はメインプロセスのみに提供されており、レンダラープロセスには提供されていません。レンダラープロセスからそれらを使うために、ipcモジュールはメインプロセスにインタープロセスメッセージを送信するのに必要です。remoteモジュールで、JavaのRMIと同じように、はっきりとインタープロセスメッセージを送信しなくてもメインプロセスオブジェクトのメソッドを呼び出せます。

レンダラープロセスからブラウザーウィンドウを作成する例:

const remote = require('electron').remote;
const BrowserWindow = remote.BrowserWindow;

var win = new BrowserWindow({ width: 800, height: 600 });
win.loadURL('https://github.com');

Note: 逆には(メインプロセスからレンダラープロセスにアクセスする)、webContents.executeJavascriptが使えます。

Remote オブジェクト

remoteモジュールから返されるそれぞれのオブジェクト(関数含む)はメインプロセスでオブジェクトを示します(リモートオブジェクトまたはリモート関数と呼ばれます)。リモートプロジェクトのメソッドを実行したり、リモート関数をコールしたり、リモートコンストラクター(関数)で新しいオブジェクトを生成したりしたとき、実際に非同期にインタープロセスメッセージが送信されます。

上の例では、BrowserWindowwin はリモートオブジェクトで、new BrowserWindowはレンダラープロセスで BrowserWindowを作成しません。代わりに、メインプロセスでBrowserWindow オブジェクトが作成され、レンダラープロセスで対応するリモートオブジェクトを返し、すなわちwinオブジェクトです。

リモート経由でのみアクセスできる enumerable propertiesに注意してください。

Remote オブジェクトのライフタイム

Electronは、レンダラープロセスのリモートオブジェクトが生きている限り(言い換えれば、ガベージコレクションされません)、対応するメインプロセスのオブジェクトは解放されないことを確認してください。リモートオブジェクトがガベージコレクションされたとき、対応するメインプロセスのオブジェクトが間接参照されます。

レンダラープロセスでリモートオブジェクトがリークした場合(マップに格納されているが解放されない)、メインプロセスで対応するオブジェクトもリークするので、リモートオブジェクトがリークしないように細心の注意を払うべきです。

文字列や数字のようなプライマリ値は、コピーして送信します。

メインプロセスにコールバックを通す

メインプロセスのコードは、レンダラーからコールバックを受け取ることができます。例えば、remoteモジュールです。この機能をとても慎重に使うべきです。

最初に、デッドロックを避けるために、メインプロセスに渡されたコールバックは非同期に呼び出されます。メインプロセスは、渡されたコールバックの戻り値を取得することを期待すべきではありません。

例えば、メインプロセスでコールされたArray.mapで、レンダラープロセスから関数を使用することはできません。:

// main process mapNumbers.js
exports.withRendererCallback = function(mapper) {
  return [1,2,3].map(mapper);
}

exports.withLocalCallback = function() {
  return exports.mapNumbers(function(x) {
    return x + 1;
  });
}
// renderer process
var mapNumbers = require("remote").require("./mapNumbers");

var withRendererCb = mapNumbers.withRendererCallback(function(x) {
  return x + 1;
})

var withLocalCb = mapNumbers.withLocalCallback()

console.log(withRendererCb, withLocalCb) // [true, true, true], [2, 3, 4]

見ることができるように、レンダラーコールバックの同期戻り値は予想されなかったとして、メインプロセスで生きている同一のコールバックの戻り値と一致しません。

第二に、メインプロセスに渡されるコールバックはメインプロセスがガベージコレクトするまで存続します。

例えば、次のコードは一目で無害なコードのように思えます。リモートオブジェクト上でcloseイベントのコールバックをインストールしています。

remote.getCurrentWindow().on('close', function() {
  // blabla...
});

りかし、明確にアンインストールするまでメインプロセスによってコールバックは参照されることを覚えておいてください。アンインストールしない場合、ウィンドウをリロードするたびに、コールバックは再度インストールされ、それぞれの再起動時にコールバックあリークします。

さらに悪いことに、前にインストールされたコールバックのコンテキストは解放されるので、closeイベントを出力されると、メインプロセスで例外が発生します。

この問題を避けるために、メインプロセスに渡されたレンダラーコールバックへの参照をクリーンアップを確認します。これにはイベントハンドラーのクリンアップも含まれ、存在しているレンダラープロセスから来るコールバックを確実にメインプロセスが守るように確認します。

メインプロセスで組み込みモジュールにアクセスする

メインプロセスの組み込みモジュールは、remoteモジュールでゲッターとして追加されるので、electronモジュールのように直接それらを使用できます。

const app = remote.app;

メソッド

remoteモジュールは次のメソッドを持ちます。

remote.require(module)

  • module String

メインプロセスで、require(module)で返されるオブジェクトを返します。

remote.getCurrentWindow()

このウェブページに属するBrowserWindow オブジェクトを返します。

remote.getCurrentWebContents()

このウェブページのWebContents オブジェクトを返します。

remote.getGlobal(name)

  • name String

メインプロセスで、nameのグローバル変数(例えば、global[name])を返します。

remote.process

メインプロセスでprocessオブジェクトを返します。これはremote.getGlobal('process')と同様ですが、キャッシュされます。