React + Redux + Electronでデスクトップアプリを開発していた際に、Rendererプロセス(React)の以下のコードでUncaught ReferenceError: require is not defined
が出て詰まってしまいました。
import { ipcRenderer, remote } from 'electron';
原因
ノードインテグレーションが無効だから。
Electronのバージョン5系では、nodeIntegration
のデフォルト値false
なっていたからでした。
nodeIntegrationとは?
XSS対策のためのオプションで無効(false
)にすることで、RendererプロセスからNode.jsの機能へのアクセスを制限することができます。
そのため、Rendererプロセス(React)でrequire
関数が呼べずにUncaught ReferenceError: require is not defined
が出てしまってたようです。
ネットで検索すると、普通にimportできるような記述をみますが、
- Electronの古いバージョンでの話(昔はデフォルトtrueだったらしい)
-
nodeIntegration: true
にしている
のどちらかだと思います。
【参考】
Electron公式ドキュメントDo not enable Node.js Integration for Remote Content
対応策
対応策は2つあります。
- ノードインテグレーションを有効にする
- preloadを使う
1. ノードインテグレーションを有効にする
オプションをtrue
にするだけです。
mainWindow = new BrowserWindow({
width: 1000,
height: 800,
webPreferences: {
nodeIntegration: true, // ココ
},
});
有効にして良いの?
ElectronでXSS攻撃を受けた場合、ユーザのPCのデータも操作されてしまう危険もあるので、false
のままにしておいた方が安全です。
ローカルで完結するようなアプリの場合は、true
にしても良いと思いますが、
データベースからユーザが入力したテキストを表示するなど、リモートコンテンツを表示する機能がある場合には意識した方が良いでしょう。
2. preloadを使う
ノードインテグレーションを有効にしたくない場合には、preloadを使いましょう。
preloadとは、他のスクリプトが実行される前にロードするスクリプトを指定できるオプションで、指定したスクリプト内では、Node.jsのAPIにアクセスできます。
そのため、以下のようにwindowオブジェクトなどに使用したいモジュールをセットできるのです。
new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: false,
preload: `${__dirname}/preload.js`, // 読み込みたいjsファイルのパス
},
});
// 以下preload.jsの内容
window.ipcRenderer = require('electron').ipcRenderer;
window.remote = require('electron').remote;
このようにしたら、あとは、Rendererプロセスでwindow.ipcRenderer
を呼び出すだけです!!
【参考】