逆引きElectron + Vue.js

[bookmark-with-image](https://github.com/unhurried/bookmark-with-image)の開発で得たElectronとVue.jsを組み合わせてネイティブアプリを開発するノウハウを整理した。

##### プロジェクトセットアップ

[electron-vue](https://github.com/SimulatedGREG/electron-vue)はVue CLI2ベースなので、Vue CLI3以降に対応した[Vue CLI Plugin Electron Builder](https://nklayman.github.io/vue-cli-plugin-electron-builder/)を利用する。

以下の通り、Vue CLIで通常通りVue.jsプロジェクトを作成した後に、electron-builderプラグインを追加すればよい。

```shell
vue create {project name}
vue add electron-builder
```

参考：https://qiita.com/jay-es/items/910db55f93c0c4c00727



##### レンダラープロセスからメインプロセスの処理を呼び出す

※ [remoteモジュールは非推奨](https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31)となっており、[Electron v10からデフォルトでは無効化される](https://www.electronjs.org/docs/breaking-changes#enableremotemodule-defaults-to-false)とのこと。以下の方法は[ipcRenderer](https://www.electronjs.org/docs/api/ipc-renderer)を利用した方法に変更予定。

以下の流れで、メインプロセスのロジックをまとめたServiceクラスを、[remote.require](https://www.electronjs.org/docs/api/remote#remoterequiremodule)を利用してレンダラープロセスから呼び出す。

* メインプロセスで実行する処理をServiceクラスとして実装する。（例：[ConfigService.ts](https://github.com/unhurried/bookmark-with-image/blob/v2.1.1/src/remote/service/ConfigService.ts)）
* [background.ts](https://github.com/unhurried/bookmark-with-image/blob/v2.1.1/src/background.ts#L14)にて、アプリ起動時に各Serviceクラスのインスタンスを登録（[RemoteServiceManager.ts](https://github.com/unhurried/bookmark-with-image/blob/v2.1.1/src/remote/RemoteServiceManager.ts)を参照）しておく。（厳密には初回利用時にインスタンス生成すれば十分ではある。）
  * メインプロセスとレンダラープロセスのコードはそれぞれでminifyされてクラス名が別になるため、デコレータ（[RemoteService.ts](https://github.com/unhurried/bookmark-with-image/blob/v2.1.1/src/remote/RemoteService.ts)）を使って、メインプロセス⇔レンダラープロセスで共有するService名を登録している。

* レンダラープロセスから必要なServiceクラスのインスタンスをremote.require経由で取得して呼び出す。（[RemoteServiceFactory.ts](https://github.com/unhurried/bookmark-with-image/blob/v2.1.1/src/remote/RemoteServiceFactory.ts)を参照）
  * メインプロセス開発用ビルド `electron:serve` ではbackground.jsにトランスパイルされ、プロダクション用ビルド `electron:build` ではindex.jsにトランスパイルされるため、どちらにも対応できるように実装している。（[参考](https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/133)）



##### ローカルデータベースを利用する

[SQLite3](https://www.sqlite.org/index.html) + [TypeORM](https://typeorm.io/) を利用する。

* ネイティブモジュールに依存しないPure JavaScript実装のデータベースとして[NeDB](https://github.com/louischatriot/nedb)があるが、開発が止まっておりElectron v6以降にも対応していないようである。（[参考](https://github.com/louischatriot/nedb/issues/492)）

* SQLite3はネイティブモジュールを扱う必要ありだが、対応する開発補助ツール（Windowsでは[A5:SQL](https://a5m2.mmatsubara.com/)など）も多くあり、[TypeORMでもサポート](https://github.com/typeorm/typeorm/blob/master/README.md#installation)されている。
* その他の候補としては[sql.js](https://github.com/sql-js/sql.js)があるが未検証。

SQLite3は以下の手順でElectron用にビルドする必要がある。

* ビルドツール（node-gypなど）をインストールする。Windowsでは[windows-build-tools](https://github.com/felixrieseberg/windows-build-tools)を使うと簡単。（[参考](https://github.com/nodejs/node-gyp#on-windows)）

  ```shell
  npm install --global --production windows-build-tools
  ```

* Electron用にSQLite3をビルドする。

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

  ※ targetには利用するElectronのバージョンを指定すること。

TypeORMのSQLite3Driverはレンダラープロセスではなくメインプロセスから呼び出す必要がある（[参考1](https://github.com/typeorm/typeorm/issues/121)、[参考2](https://github.com/typeorm/typeorm/issues/3859)）ため、[レンダラープロセスからメインプロセスの処理を呼び出す](#レンダラープロセスからメインプロセスの処理を呼び出す)の方法で実装する。



##### アイコン画像を設定する

[Vue CLI Plugin Electron Builderのドキュメント](https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/recipes.html#icons)で紹介されている[electron-icon-builder](https://www.npmjs.com/package/electron-icon-builder)を利用する。

* `public/icon.png` に配置した元画像を、各プラットフォーム向けにリサイズして `build` ディレクトリに保存してくれる。
* その他の方法としては、[electron-builderのデフォルトアイコン画像パス](https://www.electron.build/icons)（Windowsの場合は `build/icon.ico or .png` ）に画像を置くか、[electron-builderの設定でパスを指定](https://www.electron.build/configuration/win)することもできる。

（参考）Font Awesomeを使ったアイコン画像を作るときには https://gauger.io/fonticon/ が便利である。 



##### ファイル選択ダイアログを実装する

https://qiita.com/unhurried/items/b622726851d22e36dccb を参照