この記事の用途
- electron + vue.jsでモダンなデスクトップアプリ開発を行う
- C++プログラムと連携する(活用例: 機械学習アプリなど、高速な計算が必要となる場面)
- この記事では、環境構築に重点を置いて説明しています。
登場人物
- electron: Webブラウザベースで動くデスクトップアプリ開発フレームワーク
- Vue.js: フロントエンド開発フレームワーク
- node_addon_api: javaScriptからC++資産を利用するためのフレームワーク
- node_addon_apiを使ったことがない方は、こちらの記事 もご覧ください!
バニラelectron と electron-vue の違い
- はじめに、バニラelectronとの違いを列挙する
- ※ バニラelectronとは、特に拡張機能をインストールしておらず、画面を html, css, js で作成したものを指す
- バニラってどういう意味?
バニラelectron | electron-vue | |
---|---|---|
メインプロセスファイル | main.js | src/background.js |
レンダラープロセスファイル | renderer.js | src/main.js |
electronBuilderの設定 | package.jsonに記述 | vue.config.jsに記述 |
出力先フォルダ | dist | dist_electron |
.nodeファイルの読み込み | bindings | node-loader |
使用するテンプレート
electron-vueのインストール
- こちらの記事を参考にインストールする
electron-vueで C++ライブラリを使用するための準備
node-addon-apiをインストールする
-
C++ソースのビルド環境として、
node_addon_api
を利用する。- node_addon_apiの使用方法は こちらの記事 で紹介しています。
-
node_addon_apiを使って、C++ファイルをコンパイルする
- コンパイルに成功すると、プロジェクトのルートディレクトリ内に
build/Release
フォルダが生成され、そこに.nodeファイルが生成される - ※ もし、コンパイルしたC++ファイルがOpenCVなどのDLLに依存している場合、
build/Release
内に .dllファイルを設置しないといけません。
- コンパイルに成功すると、プロジェクトのルートディレクトリ内に
-
以降、node-addon-apiでビルドしたC++ライブラリを
.nodeモジュール
と呼ぶことにします。- 以下に .nodeモジュールを使用するための手順を示します。
vue.config.jsの作成
- はじめに、ルートディレクトリ(package.jsonと同階層)に
vue.config.js
を手動で作成する
nodeIntegrationの有効化
-
vue.config.js内の
pluginOptinons
セクション内に下記の記述を追加するvue.config.jsmodule.exports = { pluginOptions: { electronBuilder: { pluginOptions: { nodeIntegration: true } } } }
- 注) nodeIntegration: true はブラウザ側でのネイティブアプリの実行が可能となるが、セキュリティリスクが高まる
builderOptionsセクションの作成
-
作成したvue.config.js内に__"builderOptions"__セクションを追加する。
-
package.jsonの "build" セクション内の項目を、builderOptionsセクションへ移動する
-
注意) package.json 内に "build" セクションがあると、下記のようなエラーが発生する
errorInvalidConfigurationError: 'build' in the application package.json (\package.json) is not supported since 3.0 anymore. Please move 'build' into the development package.json
-
-
"builderOptions"内に、"extraResources"セクションを設けて、node_addon_apiでビルドした.dllと.node拡張子を登録する
-
これにより、
dist-electron/win-unpacked/resources
フォルダ内(※ windowsの場合)にビルドしたファイルが転送され、electron側で読み込めるようになるvue.config.js"extraResources": [ "./build/Release/*.node", "./build/Release/*.dll" ],
-
(補足) builderOptionsセクションの設定項目一覧
- vue.config.js内の builderOptions 内で設定できるセクション名は下記を参照のこと
node-loaderをインストールする
-
node-addon-apiでビルドした.nodeファイルを読み込むために使用する(node-loader)
- 初めに npm installを行う
npm install node-loader
- 初めに npm installを行う
-
vue.config.js内の
pluginOptinons
セクション内に下記の記述を追加するvue.config.jspluginOptions: { // ---- ここから↓ ---- // target: 'node', node: { __dirname: false, }, module: { rules: [ { test: /\.node$/, loader: 'node-loader', }, ], }, // ---- ↑ここまで ---- // electronBuilder: { ...中略 } }
-
ここまでの準備で、electron側から.nodeアプリを呼び出す準備ができた。
メインプロセスで .nodeモジュールを使用する
- src/background.jsで以下のように読み込む。
-
__non_webpack_require__
関数を使用し、.nodeファイルのパスを直接指定する -
※ バニラelectron で使用していた
require("bindings")("addon")
コマンドは使用できないbackground.jsconst path = require('path'); // pathモジュールインポート console.log("__dirname",__dirname); // Debug: ルートパスの表示 // .nodeファイルのパスを直接指定 var nodePath = path.dirname(__dirname) + '/build/Release/○○○.node'; var addon = __non_webpack_require__(nodePath); var obj = new addon.○○○(); // nodeモジュールのインスタンス化
-
※ ここでモジュールを読み込むことができるのは、vue.config.js内の "extraResourcesFiles" セクションで .nodeファイルと、.dllファイルを登録しているから。
-
レンダラープロセスで .nodeモジュールを使用する
-
preload.js
を経由して .nodeファイルを読み込む必要がある
preload.jsの作成
- src/preload.jsを手動で作成する
- vue.config.jsに以下の項目を追加する
pluginOptions: {
nodeIntegration: true,
preload: 'src/preload.js' // 追加
}
- background.jsのcreateWindow()関数内で下記を追加する
function createWindow() {
// Create the browser window.
const win = new BrowserWindow({
webPreferences: {
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
preload: path.join(__dirname, 'preload.js'), // 追加
}
})
preload.js内で .nodeモジュールを呼び出す
-
呼び出し方は、 background.jsとほぼ同じ
- 相違点は最後の1行。
window.変数名
として登録することで、レンダラープロセスから利用できる
preload.jsconst path = require('path'); // pathモジュールインポート console.log("__dirname", __dirname); // Debug: ルートパス var nodePath = path.dirname(__dirname) + '/build/Release/○○○.node'; var addon = __non_webpack_require__(nodePath); var obj = new addon.○○○(); window.obj = obj; // !重要: windowオブジェクトに紐付けることで、app.Vueから呼び出せる
- 相違点は最後の1行。
-
App.vueから、preload.jsで呼び出したモジュールを利用する
- windowオブジェクトから変数を参照する
App.Vuevar obj = window.obj; // windowオブジェクトから参照する obj.funcA();
-
- ※ ゆくゆくはcontext-bridgeを使った方がセキュアだと思います。
その他Tips
よくあるミス
- 関連するDLLを build/Releaseフォルダに置いていない
- " build/Release/○○.node が見つからない" とのエラーが出たときは、DLLも確認すること
electron + vue で複数ページのアプリを作る方法
静的ファイル(assets, images)をコピーする方法
-
vue.config.js の builderOptions内に、
extraFiles
セクションを追加するvue.config.js"extraFiles": [ "images/*.png", "config/**/.txt" ]
electron-vueで sass, scss を使う方法
-
npm install --save-dev sass-loader node-sass
- npm install 時にエラーが出たら... 古いバージョンを指定して再度インストールする
- 例:
npm install --save-dev sass-loader@10.1.1
- こちらが参考になる -> StackOverflow
- 例:
レンダラープロセスから、dialogを利用する方法
-
background.js で画面を生成する際に、
enableRemoteModule: true
オプションを追加するbackground.jsnew BrowserWindow({ webPreferences: { enableRemoteModule: true, // 追加 } });
リンク集
- ElectronでcontextBridgeによる安全なIPC通信
- __ non_webpack_require__ は、レンダラプロセスで使用できない
- electron + Reactでの開発も可能なようだ