LoginSignup
5
9

More than 3 years have passed since last update.

【環境構築】electron-vue と node_addon_api を連携し、C++とVue.jsを使ってelectronアプリを開発する

Last updated at Posted at 2021-03-28

この記事の用途

  • 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を使って、C++ファイルをコンパイルする

    • コンパイルに成功すると、プロジェクトのルートディレクトリ内に build/Releaseフォルダが生成され、そこに.nodeファイルが生成される
    • ※ もし、コンパイルしたC++ファイルがOpenCVなどのDLLに依存している場合、build/Release内に .dllファイルを設置しないといけません。
  • 以降、node-addon-apiでビルドしたC++ライブラリを .nodeモジュールと呼ぶことにします。

    • 以下に .nodeモジュールを使用するための手順を示します。

vue.config.jsの作成

nodeIntegrationの有効化

builderOptionsセクションの作成

  • 作成したvue.config.js内に"builderOptions"セクションを追加する。

    • package.jsonの "build" セクション内の項目を、builderOptionsセクションへ移動する
    • 注意) package.json 内に "build" セクションがあると、下記のようなエラーが発生する

      error
      InvalidConfigurationError: '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セクションの設定項目一覧

node-loaderをインストールする

  • node-addon-apiでビルドした.nodeファイルを読み込むために使用する(node-loader)

    • 初めに npm installを行う
      • npm install node-loader
  • vue.config.js内の pluginOptinonsセクション内に下記の記述を追加する

    vue.config.js
        pluginOptions: {
            // ---- ここから↓ ---- //
            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.js
          const 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に以下の項目を追加する
vue.config.js
    pluginOptions: {
        nodeIntegration: true,
        preload: 'src/preload.js' // 追加
    }
  • background.jsのcreateWindow()関数内で下記を追加する
src/background.js
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.js
        const 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から呼び出せる
    
  • App.vueから、preload.jsで呼び出したモジュールを利用する

    • windowオブジェクトから変数を参照する
    App.Vue
      var obj = window.obj; // windowオブジェクトから参照する 
      obj.funcA(); 
    
  • 参考にしたStackOverflow

    • ※ ゆくゆくは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 を使う方法

レンダラープロセスから、dialogを利用する方法

  • background.js で画面を生成する際に、enableRemoteModule: trueオプションを追加する

    background.js
    new BrowserWindow({
        webPreferences: {
            enableRemoteModule: true, // 追加
         }
     });
    

リンク集

5
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
9