はじめに (対象読者・この記事でわかること)
この記事は、Electron ForgeとVue 3を組み合わせてデスクトップアプリケーション開発を始めたものの、「Electronアプリが起動しない」「真っ白な画面しか表示されない」といった問題に直面している開発者を主な対象としています。
この記事を読むことで、Electron ForgeとVue 3の基本的な連携方法、特にアプリ起動時の一般的なエラーの原因とその効果的な解決策を理解し、スムーズに開発を進められるようになります。Electronのメインプロセスとレンダラープロセスの連携、ビルド設定の調整といった、つまずきやすいポイントに焦点を当てて解説します。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。 * HTML/CSSの基本的な知識 * JavaScript/TypeScriptの基本的な知識 * Vue.jsの基本的な知識 (コンポーネント、ライフサイクルなど) * Node.js/npmの基本的なコマンド操作 * 基本的なターミナル操作
Electron ForgeとVue 3:セットアップの落とし穴
ElectronはJavaScript、HTML、CSSを使ってデスクトップアプリケーションを開発できる強力なフレームワークです。中でも、Electron Forgeはプロジェクトの初期化、開発、ビルド、パッケージングまでをシンプルに管理するためのツールキットとして広く利用されています。一方、Vue 3は軽量かつ高速なフロントエンドフレームワークであり、SPA (Single Page Application) 開発において非常に人気があります。この2つを組み合わせることで、リッチなUIを持つデスクトップアプリケーションを効率的に開発できるため、多くの開発者に選ばれています。
しかし、Electron ForgeとVue 3の組み合わせは、特に初めて利用する際にいくつかの「落とし穴」があります。最もよく報告される問題の一つが、「アプリが起動しない」「真っ白な画面が表示される」といった起動エラーです。これは、Electronのメインプロセス(Node.js環境)とレンダラープロセス(ブラウザ環境でVueアプリが動作)間の連携、そして両者のビルドシステム(特にWebpackやVite)の設定が複雑に絡み合っているためです。
主な原因としては、レンダラープロセスがVueアプリケーションのビルド成果物(index.htmlやバンドルされたJavaScriptファイル)を正しく読み込めないこと、またはWebpack/Viteの設定がElectronの要件と合致していないことが挙げられます。特に、ファイルパスの解決、アセットの参照、そして開発モードと本番モードでの挙動の違いが、多くの開発者を悩ませるポイントとなります。
Vue 3アプリとElectron Forgeの正しい統合手順とエラー解決ガイド
ここでは、Electron ForgeにVue 3アプリケーションを正しく統合し、起動エラーを解決するための具体的な手順と設定について解説します。
ステップ1: Electron Forgeプロジェクトの初期化
まずは、Electron Forgeプロジェクトを初期化します。Vue 3との連携を考慮し、ここではWebpackテンプレートを使用します。(Viteテンプレートでも同様の問題が発生する可能性がありますが、本記事ではWebpackを例に進めます。)
Bash# プロジェクトディレクトリを作成 mkdir my-electron-vue-app cd my-electron-vue-app # Electron ForgeプロジェクトをWebpackテンプレートで初期化 npm init electron-app@latest . -- --template=webpack # 依存関係をインストール npm install
この段階で一度、Electronアプリが起動するか確認しましょう。
Bashnpm run start
初期状態では、Electronのロゴが表示されたシンプルなウィンドウが起動するはずです。
ステップ2: Electron ForgeへのVue 3の統合
次に、Electron ForgeのレンダラープロセスでVue 3アプリケーションを実行できるように設定します。
-
Vueと関連する依存関係のインストール:
bash npm install vue@next vue-loader@next @vue/compiler-sfcvue@next: Vue 3本体vue-loader@next: WebpackでVue単一ファイルコンポーネント (.vue) を処理するためのローダー@vue/compiler-sfc: Vue単一ファイルコンポーネントをコンパイルするためのコンパイラ
-
webpack.renderer.config.jsの修正:webpack.renderer.config.jsは、Electronのレンダラープロセスで動作するアプリケーション(今回の場合はVueアプリ)のビルド設定を定義します。このファイルをVueアプリをバンドルできるように修正します。```javascript const rules = require('./webpack.rules'); const plugins = require('./webpack.plugins');
// Vue Loader プラグインをインポート const { VueLoaderPlugin } = require('vue-loader');
rules.push( { test: /.css$/, use: [{ loader: 'style-loader' }, { loader: 'css-loader' }], }, // Vue ファイルを処理するためのルールを追加 { test: /.vue$/, loader: 'vue-loader', } );
module.exports = { module: { rules, }, plugins: [ ...plugins, // VueLoaderPlugin を追加 new VueLoaderPlugin(), ], resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue'], // .vue ファイルを解決できるように拡張子を追加 alias: { 'vue': '@vue/runtime-dom' // Vue 3のバンドルエイリアスを設定 } }, }; ```
-
Vue アプリケーションのエントリポイントの作成:
src/renderer.jsをVueアプリケーションのエントリポイントとして使用します。このファイルでVueアプリをマウントします。```javascript // src/renderer.js import { createApp } from 'vue'; import App from './App.vue'; // 後で作成するVueコンポーネント
// VueアプリのCSSをインポート(必要であれば) import './index.css';
createApp(App).mount('#app'); ```
-
Vue コンポーネントの作成:
src/App.vueを作成し、シンプルなVueコンポーネントを定義します。```vue
```Hello Electron with Vue 3!
This is a desktop app.
-
src/index.htmlの修正:src/index.htmlはレンダラープロセスがロードするHTMLファイルです。Vueアプリケーションをマウントする要素 (<div id="app"></div>) が必要です。html <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Electron with Vue 3</title> <!-- 必要に応じてスタイルシートをリンク --> <link rel="stylesheet" href="./index.css" /> </head> <body> <!-- Vue アプリケーションがマウントされる場所 --> <div id="app"></div> </body> </html>
これで基本的なセットアップは完了です。再度 npm run start を実行し、Electronアプリが起動し、Vueコンポーネントが表示されるか確認してください。
ハマった点やエラー解決
上記の手順でうまくいかない場合、いくつかの一般的な落とし穴があります。
-
エラー:
A JavaScript error occurred in the main processまたはウィンドウが真っ白- 原因: レンダーラープロセスが正しくロードされていない、またはVueアプリケーションのJavaScriptファイルがバンドルされていないか、パスが間違っている可能性があります。
- 具体的なメッセージ例:
Failed to load URL: file:///path/to/my-electron-vue-app/.webpack/renderer/main_window/index.html with error: ERR_FILE_NOT_FOUND- コンソールに
Cannot find module 'vue'のようなエラーが表示される。
- デバッグ方法:
- Electron開発者ツールを開く: アプリ起動後に
Ctrl+Shift+I(Windows/Linux) またはCmd+Option+I(macOS) で開発者ツールを開き、ConsoleタブやNetworkタブでエラーを確認します。Networkタブで必要なファイル(JS, CSS, HTML)が正しくロードされているか確認します。 forge.config.jsのrenderer設定を確認。Webpackが指定されたエントリポイントをバンドルできているか。webpack.renderer.config.jsのoutput.publicPathがElectron環境と合致しているか確認(通常はWebpack Forgeのデフォルトで問題ないはずですが、Viteなどではbase: './'が重要)。
- Electron開発者ツールを開く: アプリ起動後に
-
エラー:
Module parse failed: Unexpected token (1:0) You may need an appropriate loader to handle this file type(.vueファイル関連)- 原因:
webpack.renderer.config.jsでvue-loaderが正しく設定されていないか、@vue/compiler-sfcがインストールされていない。 - 解決策:
webpack.renderer.config.jsにvue-loaderのルールとVueLoaderPluginが正しく追加されているか確認してください。npm install vue-loader@next @vue/compiler-sfcが完了しているか確認。
- 原因:
-
エラー:
[Vue warn]: Failed to resolve component: AppまたはCould not find root element #app- 原因: Vueアプリケーションのエントリポイント (
src/renderer.js) でApp.vueが正しくインポートされていないか、src/index.htmlに<div id="app"></div>が存在しない、またはIDが間違っている。 - 解決策:
src/renderer.jsでimport App from './App.vue';が正しいパスを指しているか確認。src/index.htmlに<div id="app"></div>があり、src/renderer.jsでmount('#app')とIDが一致しているか確認。
- 原因: Vueアプリケーションのエントリポイント (
-
開発モードでは動くが、
npm run makeでビルドした後に起動しない- 原因: 開発モードと本番ビルドでパスの解決方法や環境変数の扱いが異なるため。特にアセットのパス。
- 解決策:
forge.config.jsで本番ビルド時のassetsパスやpublicPathの設定を確認。- Vue側(Viteの場合
vite.config.jsのbase: './'など)で、ビルド後の相対パス参照を考慮した設定になっているか確認。 electron-forgeはデフォルトでprocess.env.NODE_ENVをproductionに設定するため、それに応じたパス解決が必要です。
解決策
上記のハマった点のほとんどは、webpack.renderer.config.js の適切な設定と、ファイルパスの整合性を確認することで解決できます。
1. webpack.renderer.config.js の再確認と修正ポイント:
rules配列に.vueファイルをvue-loaderで処理する設定があるか?javascript { test: /\.vue$/, loader: 'vue-loader', }plugins配列にnew VueLoaderPlugin()が含まれているか?javascript const { VueLoaderPlugin } = require('vue-loader'); // ... plugins: [ // ... new VueLoaderPlugin(), ],resolve.extensionsに.vueが追加されているか?javascript resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue'], },- Vue 3 の ESM ビルドを解決するための
aliasが設定されているか?javascript resolve: { // ... alias: { 'vue': '@vue/runtime-dom' // Vue 3のバンドルエイリアス } },これはVue 3のさまざまなビルド(フルバンドル、ランタイムのみなど)に対応するために必要となることがあります。特にレンダラープロセスがブラウザ環境であることを考慮し、DOMレンダラーを使用するよう指定します。
2. src/renderer.js と src/App.vue の連携:
src/renderer.jsでApp.vueが正しくインポートされているか確認 (import App from './App.vue';)src/renderer.jsでcreateApp(App).mount('#app');が正しく呼び出されているか確認src/index.htmlにid="app"を持つ要素が存在するか確認
3. メインプロセスとレンダラープロセスのパス解決:
src/main.js (または src/index.js) における mainWindow.loadURL() の部分が重要です。
Electron ForgeのWebpackテンプレートを使用している場合、通常は以下のようになります。
Javascriptimport { app, BrowserWindow } from 'electron'; // ... const createWindow = () => { const mainWindow = new BrowserWindow({ height: 600, width: 800, webPreferences: { preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, // Node.jsの機能をレンダラープロセスで利用可能にするか(セキュリティに注意) // nodeIntegration: true, // コンテキスト分離を有効にするか(セキュリティ推奨) // contextIsolation: false, }, }); // MAIN_WINDOW_WEBPACK_ENTRY は webpack.renderer.config.js のバンドル結果を指す mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY); // ... };
MAIN_WINDOW_WEBPACK_ENTRY はElectron ForgeがWebpackを通じて自動的に注入する変数で、レンダラープロセスのエントリポイント(通常はバンドルされたHTMLファイル)のURLを指します。この変数が正しく解決されない場合も起動エラーの原因となります。
ポイント: Electron ForgeのWebpackテンプレートは、レンダラープロセスのバンドルを自動的に適切なパスに配置してくれます。そのため、自分で file:// や path.join(__dirname, ...) を使ってVueのビルド結果を指す必要はほとんどありません。もし別途Vue CLIやViteで作成したプロジェクトを直接読み込みたい場合は、mainWindow.loadURL() のパスをVueのビルド成果物(例: dist/index.html)を指すように調整する必要がありますが、その場合は webpack.renderer.config.js を使わず、Electron Forgeの plugin-webpack の代わりに plugin-custom などを使うか、Electron ForgeのWebpack設定を深く理解して調整する必要があります。一般的には、本記事で説明したように、Electron ForgeのWebpack設定にVueを直接統合するアプローチが最もシンプルで堅牢です。
まとめ
本記事では、Electron ForgeとVue 3を組み合わせたデスクトップアプリケーション開発において、アプリが起動しないという一般的なエラーに焦点を当て、その原因と具体的な解決策を解説しました。
- Electron ForgeのWebpack設定 (
webpack.renderer.config.js) とVue 3の連携が重要 です。特にvue-loaderとVueLoaderPluginの適切な設定、そしてresolve.extensionsやaliasの調整が成功の鍵となります。 - メインプロセスとレンダラープロセスのパス解決 を理解し、開発者ツールを活用してエラーを特定することがデバッグにおいて不可欠です。
- 開発モードと本番ビルドでの挙動の違い を意識し、それぞれで正しく動作するか確認することが、リリースに向けた安定性を確保します。
この記事を通して、Electron ForgeとVue 3のセットアップにおけるつまずきやすい点を克服し、デスクトップアプリケーション開発をスムーズに進められるようになったことでしょう。
今後は、ElectronのIPC通信を用いたメインプロセスとレンダラープロセスの連携、ネイティブモジュールの利用、自動アップデートの実装といった発展的な内容についても記事にする予定です。
参考資料