Windows 上で Electron + sqlite3 のアプリを動かそうとするとエラーになる場合の対処法

# 現象

Macで開発していたElectronアプリをWindowsで動かしたところ、SQLite3まわりでエラーが起こっているというメッセージが表示され、実際にSQLite3が使えない状態になりました。

![error_dialog.png](https://qiita-image-store.s3.amazonaws.com/0/43328/ce2176fe-9e6f-946a-e627-7dbce35a908f.png)


# 対処法
## 事前調査

なにが起こっているのかを調べます。上のダイアログは一番重要な部分が抜けているので、例外ハンドラを追加してログに出力します。メインプロセスのjsファイルに以下を追加してください。

```js:main.js
process.on('uncaughtException', function (error) {
    console.error(error);
});
```

これで再度アプリを起動すると、エラーメッセージが表示されるタイミングで、コマンドプロンプトにエラーログが残ります。私の場合は下記のような出力でした（一部伏せ字「***」）

```
{Error: Cannot find module '***\node_modules\sqlite3\lib\binding\electron-v1.3-win32-x64\node_sqlite3.node'
    at Module._resolveFilename (module.js:440:15)
    at Function.Module._resolveFilename (***\AppData\Roaming\npm\node_modules\electron-prebuilt\dist\resources\electron.asar\common\reset-search-paths
.js:35:12)
    at Function.Module._load (module.js:388:25)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (***\node_modules\sqlite3\lib\sqlite3.js:4:15)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12) code: 'MODULE_NOT_FOUND' }
```

一行目↓が重要ですね。実際にフォルダを覗いてみると、このパスのファイルがありませんでした。

```
Cannot find module '***\node_modules\sqlite3\lib\binding\electron-v1.3-win32-x64\node_sqlite3.node'
```

## sqlite3をビルド

`node-gyp`をインストールします。

```
npm install -g node-gyp
```

* Windowsの場合、Visual Studio がインストールされている必要があるそうです（すでにインストールされていたので未確認）。**VS2015 Community や VS Express for Desktop** でよいとのこと。私の環境は後者が入っています。

* また、`node-gyp`は **python2系** が必要です。3は動きません。Windowsでのpython管理は Conda が便利です。（参考：[データサイエンティストを目指す人のpython環境構築 2016](http://qiita.com/y__sama/items/5b62d31cb7e6ed50f02c)）

**====追記 (2019年3月27日)====**
node-sqlite3 v4.0.5 で確認したところ方法が変わっていました。
[README.md](https://github.com/mapbox/node-sqlite3) の Custom builds and Electron のセクションに従います。
はじめに入れてしまった sqlite3 を除去しておいてください。

```
npm remove sqlite3
```

続いて下記コマンドを実行します。
`--target=x.x.x` を `electron -v` で表示されるバージョンに書き換えてください。

```
npm install sqlite3 --build-from-source --save --runtime=electron --target=x.x.x --dist-url=https://atom.io/download/electron
```

以上で動きました。

**====追記ここまで====**
**（以下は古いバージョン向けです）**

インストールが終わったらsqlite3をビルドします。Electronアプリのフォルダを`$APP$`と表記します。

```
cd $APP$\node_modules\sqlite3
npm install
npm run prepublish
```

次に↓のコマンドを実行しますが、適宜書き換えが必要ですので、下の表を参考にしてください。

```
node-gyp configure --module_name=node_sqlite3 --module_path=../lib/binding/[dir]
node-gyp rebuild --target=[electron-v] --arch=[arch] --target_platform=[platform] --dist-url=https://atom.io/download/atom-shell --module_name=node_sqlite3 --module_path=../lib/binding/[dir]
```

| placeholder | value |
|:--|:--|
| `[dir]` | 事前調査で「Cannot find」と言われたディレクトリの名前 |
| `[electron-v]` | Electronのバージョン。<br>`electron -v`で調べる |
| `[arch]` | 32bitの場合 `ia32`<br>64bitの場合 `x64` |
| `[platform]` | Windowsの場合 `win32`<br>Macの場合 `darwin` |

私の場合は、Electron 1.3.1、Windows 64bitなので、下記のようになります。

```
node-gyp configure --module_name=node_sqlite3 --module_path=../lib/binding/electron-v1.3-win32-x64
node-gyp rebuild --target=1.3.1 --arch=x64 --target_platform=win32 --dist-url=https://atom.io/download/atom-shell --module_name=node_sqlite3 --module_path=../lib/binding/electron-v1.3-win32-x64
```

これで動くようになるはずです。

# 編集後記
* 配布のとき各環境用にビルドする必要があるので、`package.json` にスクリプト化しておいた方がよいと思っています

# 参考
[electron でsqlite3を使うときに起こるエラー](http://qiita.com/shghdyji/items/20d2a913e3e492726c55)
[WindowsのElectronでsqlite3が動かない人のためのバッチファイル](http://smellman.hatenablog.com/entry/2016/03/18/101539)