Electron 10.0.0が先日リリースされて、remote module
がデフォルトで無効になりました。
バージョンを上げた時に、一部機能が動かなくなる場合など出てくると思いますので
- そもそも
remote module
とは - なぜ
remote module
を使うとよくないのか
を整理してみたので、共有してみたいと思います。
この内容は2020年02月に開催されたCovalenceConf 2020のセッション(Jeremy Apthorp: Remote Module Considered Harmful )を元にまとめた内容であり、コードは動画内のものを引用しています。
remote module
とは
remote module
を使うことでレンダラプロセス内であたかもメインプロセス内のオブジェクトを直接触れるように見せかけることができます。
例えば、remote module
を使って、レンダラプロセスで以下のようなサーバーを起動するようなコードを書くことができます。が、実際にはメインプロセスでソケットが開いていて、3000番ポートにリクエストがあった際、メインプロセスからレンダラプロセスをIPCで通信します。
// CovalenceConf 2020のセッション // (Remote Module Considered Harmful )から引用 // Renderer process const remote = require('electron').remote const remoteHttp = remote.require('http') const s = remoteHttp.createServer((req, res) => { res.setHeader('Access-Control-Allow-Origin, '*') res.end('yay') }) s.listen(3000, () => { fetch('http://localhost:3000') .then(r=> r.text()) .then(t => alert(t)) })
問題が発生する要因
remote moduleを通してメインプロセスとレンダラプロセスのIPC通信を実現する手段として、proxy objectsというものが介在しているようです。
まずい点その①遅い(パフォーマンス問題)
proxy objects
が介在すると気がつかない間にIPC通信が増えてしまい、気がつかない間にパフォーマンスに問題が発生するケースがあるようです。
動画内では、以下のコードスニペットをあげており、この短いコードの中で9回IPC通信が行われます。
また、そもそもレンダラプロセスからメインプロセスのオブジェクトにアクセスすると、IPC通信を介することでローカルオブジェクトへのアクセスより1000倍遅くなるようです。
// CovalenceConf 2020のセッション // (Remote Module Considered Harmful )から引用 // Main process global.thing = { rectangle: { getBounds() { return { x, y, width, height } } setBounds(bounds) { /* ... */ } } } // Renderer process let thing = remote.getGlobal('thing') let { x, y, width, height} = thing.rectangle.getBounds() thing.rectangle.setBounds( { x, y, width, height: height + 100 })
パフォーマンス問題が発生することで、プロセス間の非同期処理が失敗したり、デバッグが難しい問題を引き起こすことがあるようです。
まずい点その②セキュリティ問題がある
remote module
を使ってレンダラプロセスからメインプロセスにIPC通信する際、ELECTRON_BROWSER_FUNCTION_CALL
というIPCメッセージを送れると、メインプロセスの全ての権限が与えられてなんでもできちゃうという潜在的な問題があるようです。
PNGやjsonを読み込むなど信頼できないコードが含まれる場合もある(セキュリティ脆弱性:NVD - CVE-2019-7317、NVD - CVE-2014-3188)ので、セキュリティホールになるようです。
remote module
を無くすためのElectronの展開
以下のElectronのバージョンでそれぞれ対応を行い、徐々にremote module
を無くす予定のようです。
- v9: 明示的に有効にせず
remote module
を使っている場合、警告を出す - v10: デフォルトで
remote module
を無効に - (今後) v12:
require('electron').remote
またはenableRemoteModule: true
にしている場合、警告を出すように - (今後) v14:
require('electron').remote
を削除
remote module
を無くすためのアプリケーション側の対応
現状 remote
モジュールを使って、レンダラプロセスからあたかもローカルオブジェクトのようにメインプロセス内のオブジェクトを使っている場合、今後どうしたら良いのか。
対応としては2つあるようです。
①明示的にIPC通信で処理するように置き換える
remote module
を使ってメインプロセス内のオブジェクトを参照し、暗黙的にIPC通信が行われることによって様々な問題が発生するので、明示的なIPC通信に置き換えていくことを推奨しているようです。
② 移管されるelectron-userland/remote
を使う
build-inで提供されている remote module
は将来的に削除され、electron-userland/remote
に移管されるのでそれを使い続けるというのもできるようです。