【Electron】nodeIntegration: falseのまま、RendererプロセスでElectronのモジュールを使用する


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つあります。

  1. ノードインテグレーションを有効にする
  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を呼び出すだけです!!

【参考】