Vue.jsとElectronを使って、マルチプラットホームで動作するアプリケーションを開発しています。
vue-cli-plugin-electron-builderを使っていますが、そのときに、がっつりはまってしまったことについて共有します。
アプリケーションのゴール
開発しているアプリケーションのゴールは以下の通りです。
- データベースは、NeDBを使う。
- REST APIサーバーとデータのやりとりを行う。
- MQTTでデータの送受信を行う。
はまりネタ
NeDBのデータがIndexedDBに格納される
Vue.jsプログラムの中で、const nedb = require('nedb')
と書くと、データベースはブラウザのIndexedDBに作成されます。
NeDBはテキストファイル(JSONファイル)で中を見ることができ、他の環境に移すことができるので便利なのですが、IndexedDBに格納されるとこの利点が得られません。
Vue.jsの中で使っている訳ですので、IndexedDBに格納されるのは当たり前なのですが、何とかテキストファイルとして扱えるようにしたいと、調査開始。
見つけました。その方法。
以下のように書くと、ElectronでNeDBを使うことができるようになります。そうすると、ちゃんとテキストファイルとしてデータベースが作成できます(アプリケーションフォルダのdbフォルダの下になります。
import { remote } from 'electron'
// データベースファイルパス名を決める
const databasePath = path.join( // eslint-disable-next-line
(process.env.NODE_ENV === 'production') ? __dirname : __static,
'../db/',
)
// NeDbを作成する
const Database = remote.require('nedb')
// データベースを作成する
db = new Database({
filename: path.join(databasePath + 'plan.db'),
autoload: true
})
プログラム的には、Vue.js(Renderer)とElectron(Main)が、IPC通信を行うようです。確かにChrome Dev Toolのnetworkを見るとそんな動きをしています。
オーバーヘッドはありそうです。
NeDBがundefined
デバッグしたり、electron:serveで動かしている分には問題ないのですが、electron:buildしたものを動かすと、NeDBがundefinedだとエラーになります。
remote.require('nedb')
と書いたので、Vue.jsが必要なモジュールだと認識しないのでしょう(推測)
かといって、IndexedDBだと使い勝手が悪いし、何よりデータを別の環境に持って行けないのが痛い。
何かいい方法はないものかといろいろと試しました。結果、プロジェクトのルートにvue.config.jsと言うファイルを作り、以下のように記述することで解決しました。
module.exports = {
pluginOptions: {
electronBuilder: {
externals: ['nedb', 'fs-extra']
}
}
}
electron:buiuldするとapp.asarが使われていて削除できないと言われる
electron:buildすると、app.asarが使われていて削除できないと言われます(もちろん、英語で)
Windows10を立ち上げてすぐにビルドしても同じエラーが出ます。何度やってもエラーになります。ごくたまに成功します。
犯人は、VisualStudio Codeでした。以下の手順で設定します。
- ファイル->基本設定->設定を開きます。
-
files.watcherExclude
を検索します。 -
**/win-unpacked/**
を追加します。 - 設定タブを閉じます。
- VisualStudio Codeを再起動します。
これで、かなりの確率でelectron:buildできます。
electron:buildするときに独自ファイルを追加したい
アプリケーションを動作させるときに設定ファイルを使うことってありますよね?昔で言えばiniファイルとか。
このファイルのひな形を提供する方法です。
プロジェクトのルートにあるparameters.jsonと言うファイルを一緒にビルドして配付します。
vue.config.jsに以下のように記述します。これで、アプリケーションフォルダのresourceフォルダに配置されます。
module.exports = {
pluginOptions: {
electronBuilder: {
builderOptions: {
extraResources: [
'parameters.json'
]
}
}
}
}