Electron で jQuery 使う場合の注意点

Electron で UIkit を使っていたらハマったので覚書。
問題点としては、

  • Electron で jQuery を使おうとするとエラーが出た
  • 上記の問題を解決した結果、gulp のライブリロードが動作しなくなった

という2つの不具合が発生した。
先に書いておくと手元では下記の対応で問題なく動作したが JavaScript にそこまで詳しくはないのでこれが最善かどうかは不明です。

動作環境

  • Electron v1.7.5
  • jQuery v3.2.1
  • UIkit v3.0.0-beta.30

Electron で UIkit3(jQuery) を使う場合の問題点

Electron で UIkit3 とそれに依存している jQuery を使おうとすると

Uncaught TypeError: Cannot use 'in' operator to search for 'default' in undefined

というようなエラーがでる。
これは Electron と jQuery が競合してるからぽいらしい?(このあたりはよくわかってない…。
とりあえず、間接的でも Electron で jQuery を使う場合は以下のような設定を追加することで対処することが出来る。

BrowserWindow の生成オプションを追加する

BrowserWindow を作る際に nodeIntegrationfalse に設定することで解決することが出来る。

const {BrowserWindow} = require('electron')
let win = new BrowserWindow({
  webPreferences: {
    // この設定を追加する
    nodeIntegration: false
  }
})
win.show()

HTML 側で jQuery を読み込む前に対処する

HTML 側で jQuery を読み込む前に以下のようなコードを挿入することで解決する事が出来る。

<head>
<script>
window.nodeRequire = require;
delete window.require;
delete window.exports;
delete window.module;
</script>
<script type="text/javascript" src="jquery.js"></script>
</head>

上記のどちらか一方で解決することができるので対処しやすい方を選択するとよいだろう。

gulp を使ったライブリロードを動作させる

上記の設定で Electron と jQuery が競合する問題は解決した。
しかし、今度は gulp を使ったライブリロードが動作しなくなってしまったので対処法を書いておく。
gulp を使ったライブリロードを行う場合、HTML 側で

<script>
require('electron-connect').client.create()
</script>

というようなスクリプトを追加する必要がある。
しかし、先ほど対処した方法では require(や exportmodule)が削除されてしまい、上記のスクリプトがエラーになってしまう。

スクリプトの定義順を変える

本来は import などを使うべきなのだろうが、手元だと上手く動作しなかったので定義順を変えることで対処した。

<head>
<script>
require('electron-connect').client.create()
window.nodeRequire = require;
delete window.require;
delete window.exports;
delete window.module;
</script>
<script type="text/javascript" src="jquery.js"></script>
</head>

これで動作するはずである。
ちなみに nodeIntegration を追加する方法だと対処できないので HTML 側で対処を行う必要がある。

参考