Nuxt Modulesを使ってNuxt3にElectronを導入しよう!
はじめに
この記事はNuxt3のアプリケーションに、Nuxt Modulesを利用してElectronを導入する方法をハンズオン形式でご紹介します。
残念なことに、Electron用のNuxt Modulesであるnuxt-electron
はv0.7.0
において、Nuxtのバージョンがv3.6.5
より大きい場合、正しく動作しません。
devモードで起動した際、Electronのウィンドウが無限リロードしてしまいます。
詳細は以下のIssuesをご覧ください。
そこで、今回は正常に動作するバージョンまでNuxtのバージョンをダウングレードさせることで対応します。
Nuxtの最新版で動作する暫定的な方法も存在します。
それについては以下の記事を参照してください。
Nuxt Modulesとは
Nuxtの提供するモジュールシステムです。
フレームワークを拡張する機能を簡単に導入できます。
Electronとは
JavaScript、HTML、CSSを利用してデスクトップアプリを作成できるフレームワークです。
環境
疎通確認を行った環境です。
Node: v20.13.1
Nuxt: v3.6.5
Electron: v31.0.1
nuxt-electron: v0.7.0
パッケージマネージャー: npm
Nuxt Electronの導入
前提として必要なものは以下になります。
- Node.js
v18.0.0
以上 - CLI(ターミナル、コマンドプロンプト、etc.)
- テキストエディタ
1. Nuxtアプリケーションのセットアップ
-
直下にNuxtプロジェクトを作成したいフォルダで
nuxi init
を使ってスタータプロジェクトを作成npx nuxi@latest init <project-name> --no-install --package-manager=npm
実行するとGitを初期化するかどうかを聞かれます。
お好みのものを指定してください。
※Gitの設定に関しては以降の手順に関与しません。--no-installオプションについて
Nuxtのバージョンをダウングレードする必要があるため、同時にinstallを行わないオプションを付与しています。
Nuxt Docs > API > Commands > nuxi init --no-install--package-manager=npmオプションについて
利用するパッケージマネージャーとして
npm
を指定しています。
そのほかのパッケージマネージャーの指定も可能ですが、以降の手順はnpm
を選択した場合のものです。
Nuxt Docs > API > Commands > nuxi init --package-manager -
作成したNuxtプロジェクトに移動
cd <project-name>
-
package.json
でnuxtのバージョンを3.6.5
に変更
テキストエディタでpackage.json
を開き、以下のように編集します。{ "name": "nuxt-app", "private": true, "type": "module", "scripts": { "build": "nuxt build", "dev": "nuxt dev", "generate": "nuxt generate", "preview": "nuxt preview", "postinstall": "nuxt prepare" }, "dependencies": { - "nuxt": "^3.11.2", + "nuxt": "3.6.5", "vue": "^3.4.27", "vue-router": "^4.3.2" } }
-
nuxt.config.tsのdevtoolsオプションをfalseにする
Nuxt DevToolsの導入にはNuxt
v3.9.0
以上が必要です。Nuxt DevToolsにはNuxt v3.9.0以上が必要です。
Nuxt DevTools Docs > Guide > Getting Starteddevtoolsオプションを無効化しない場合、コマンドを実行するたびにNuxt DevToolsをインストールするかを尋ねられます。
nuxt.config.ts// https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({ - devtools: { enabled: true }, + devtools: { enabled: false }, });
-
パッケージをインストールする
npm install
-
devモードでNuxtアプリケーションが起動できることを確認
npm run dev -- -o
オプションの意味
devモード起動時に渡した
-o
は自動的にブラウザのページを開くオプションです。
nuxiに実装されています。
Nuxt Docs > API > Commands > nuxi devまた、その直前についている
--
はnpmオプションの終了を示す区切り文字です。
これ以降の引数はスクリプトに直接渡されます。
-o
オプションはnuxiに実装されているため、スクリプトに直接引数を渡さなければ動作しません。
npm Docs > CLI > Commands -npm-run-script
参考
上記の手順はNuxtの公式ドキュメントを参考に構成しています。
2. Nuxt Electronをinstall
の5つのパッケージを追加します。
npm install --save-dev nuxt-electron vite-plugin-electron vite-plugin-electron-renderer electron electron-builder
3. nuxt.config.tsのmodulesにelectronを追加
nuxt.config.ts
にmodules
プロパティを追加し、nuxt-electron
を要素に含む配列を値として設定します。
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: false },
+ modules: ["nuxt-electron"],
});
modules
プロパティの詳細は以下を参照してください。
4. electronの型情報をNuxtに追加
npx nuxi prepare
このコマンドを実行することで、nuxt.config.ts
にElectronの設定を追加する際に型補完を利用できるようになり、型エラーも出なくなります。
prepareコマンドはアプリケーションに.nuxtディレクトリを作成し、型を生成します。
Nuxt Docs > API > Commands > nuxi prepare
※devモードで起動した際、buildを実行した際などにも型情報が更新されます。
5. nuxt.config.tsにelectronの設定を追加
electron
プロパティに設定を追加することで、Nuxt ModulesのElectronに対してオプションを設定できます。
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
modules: ["nuxt-electron"],
+ electron: {
+ build: [
+ {
+ entry: "electron/main.ts",
+ },
+ ],
+ },
+ ssr: false,
});
この設定はnuxt-electronのREADMEを参考にしています。
詳しい説明
build
オプションには複数のエントリビルドを指定できます。
これにはメインプロセス、プリロードスクリプト、ワーカープロセスなどが含まれます。
また、ssr
オプションをfalse
に設定する理由については以下のIssuesに基づくものです。
クライアントサイドのスタイルシートが正しくビルドされない問題を回避するための措置です。
electron-env.d.ts
を作成する
6. electronで利用する環境変数の型を定義します。
プロジェクトのトップレベルにelectron-env.d.ts
のコードは以下になります。
/// <reference types="vite-plugin-electron/electron-env" />
declare namespace NodeJS {
interface ProcessEnv {
APP_ROOT: string
VITE_PUBLIC: string
}
}
electron/main.ts
を作成する
7. アプリケーションの作成、その設定や挙動を記述します。
プロジェクトのトップレベルにelectron
フォルダを作成し、その中にmain.ts
を作成します。
これは5. nuxt.config.tsにelectronの設定を追加にて、buildのentryとしてパスを設定したファイルです。
import { app, BrowserWindow } from "electron";
let win: BrowserWindow | null;
const createWindow = () => {
win = new BrowserWindow();
if (process.env.VITE_DEV_SERVER_URL) {
win.loadURL(process.env.VITE_DEV_SERVER_URL);
}
};
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
win = null;
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
app.whenReady().then(() => {
createWindow();
});
Electronの準備が終わったことを検知し、起動したdevサーバーのURLをElectronで開きます。
window-all-closed
、activate
のイベント発火時、プロセスの削除、起動を制御しています。
詳しい説明
BrowserWindow
BrowserWindow
ブラウザウィンドウを作成、制御できるモジュールです。
アプリのウィンドウの見た目や動作などを変更するメソッドが用意されています。
loadURL
URLを受け取り、ブラウザウィンドウでそれを読み込みます。
process.env.VITE_DEV_SERVER_URL
process.env.VITE_DEV_SERVER_URL
DevモードでNuxtアプリケーションが起動している際のURLが格納されている環境変数です。
nuxt-electronで実装されているようです。
app
app
Electronアプリケーションのイベントライフサイクルを制御するモジュールです。
アプリケーションの状態に関するイベントが発生し、それらを制御するメソッドが用意されています。
window-all-closedイベント
全てのウィンドウが閉じられたときに発生するイベントです。
今回の実装では、WindowsとLinuxの一般的なアプリケーションのライフサイクルと同等の挙動を実現するために利用されています。
この実装により、すべてのウィンドウが終了した場合にアプリケーションを完全に終了します。
activateイベント
macOS環境でにおいて、アプリケーションがアクティブになったタイミングで発生するイベントです。
今回の実装では、macOSの一般的なアプリケーションのライフサイクルと同等の挙動を実現するために利用されています。
この実装により、ウィンドウを開いていなくても起動し続け、ウィンドウがないときにアプリをアクティブにすると新規ウィンドウが開きます。
whenReady
Electronの初期化を検知し、そのタイミングで実行されるメソッドです。
これにより、Electronがアプリケーションをロードする準備が整ったあとにそれらを実行できます。
そのほかにもブラウザをカスタマイズする設定が存在します。
詳細は以下を参照してください。
8. package.jsonのmainフィールドを設定
{
"name": "nuxt-app",
"private": true,
"type": "module",
+ "main": "dist-electron/main.js",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"nuxt": "3.6.5",
"vue": "^3.4.27",
"vue-router": "^4.3.2"
},
"devDependencies": {
"electron": "^30.0.9",
"electron-builder": "^25.0.0-alpha.9",
"nuxt-electron": "^0.7.0",
"vite-plugin-electron": "^0.28.7",
"vite-plugin-electron-renderer": "^0.14.5"
}
}
9. 起動を確認
npm run dev
上記のコマンドを実行すると、Electronのウィンドウが起動し、Nuxtのスタートページが表示されるはずです。
アプリケーションのビルド
ビルドしたアプリケーションを正しく動作させるためにはdevモードでの動作環境に追加で設定が必要になります。
elecrton/main.ts
にコードを追加する
ビルド後のindex.html
のパスを用意し、それをロードするようなコードを追加します。
import { app, BrowserWindow } from "electron";
+ import path from "node:path";
+ process.env.APP_ROOT = path.join(__dirname, "..");
+ export const RENDERER_DIST = path.join(process.env.APP_ROOT, ".output/public");
+ process.env.VITE_PUBLIC = process.env.VITE_DEV_SERVER_URL
+ ? path.join(process.env.APP_ROOT, "public")
+ : RENDERER_DIST;
let win: BrowserWindow | null;
const createWindow = () => {
win = new BrowserWindow();
if (process.env.VITE_DEV_SERVER_URL) {
win.loadURL(process.env.VITE_DEV_SERVER_URL);
- }
+ } else {
+ win.loadFile(path.join(process.env.VITE_PUBLIC!, "index.html"));
+ }
};
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
win = null;
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
app.whenReady().then(() => {
createWindow();
});
package.json
を編集する
version
プロパティの追加、type
プロパティの削除、ビルド用コマンドを追加の3つを行います。
すべての変更を反映したpackage.jsonは以下になります。
{
"name": "nuxt-app",
"private": true,
- "type": "module",
"main": "dist-electron/main.js",
+ "version": "0.0.0",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
+ "build:win": "nuxt build --prerender && electron-builder --win",
+ "build:mac": "nuxt build --prerender && electron-builder --mac",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"nuxt": "3.6.5",
"vue": "^3.4.27",
"vue-router": "^4.3.2"
},
"devDependencies": {
"electron": "^30.0.9",
"electron-builder": "^25.0.0-alpha.9",
"nuxt-electron": "^0.7.0",
"vite-plugin-electron": "^0.28.7",
"vite-plugin-electron-renderer": "^0.14.5"
}
}
詳しい説明
version
プロパティの追加
1. バージョンを指定しないとelectron-builder
でのビルド時にエラーが発生し、ビルドが完了できません。
⨯ Please specify 'version' in the package.json (D:\Zenn\playground\version-test\package.json)
{
"name": "nuxt-app",
"private": true,
"type": "module",
"main": "dist-electron/main.js",
+ "version": "0.0.0",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"nuxt": "3.6.5",
"vue": "^3.4.27",
"vue-router": "^4.3.2"
},
"devDependencies": {
"electron": "^30.0.9",
"electron-builder": "^25.0.0-alpha.9",
"nuxt-electron": "^0.7.0",
"vite-plugin-electron": "^0.28.7",
"vite-plugin-electron-renderer": "^0.14.5"
}
}
type
プロパティの削除
2. ES Moduleを利用したままビルドを行うと、ビルドしたアプリケーション実行時にエラーが発生してしまいます。
A JavaScript error occurred in the main process
Uncaught Exception:
ReferenceError: __dirname is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and
'D:\Zenn\playground\module-test\release\0.0.1\win-unpacked\resources\app.asar...\package.json'
contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file
extension.
at file:///D:/Zenn/playground/module-test/release/0.0.1/win-unpacked/resources/app.asar...:31
at ModuleJob.run (node:internal/modules/esm/module_job:222:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
at async node:electron/js2c/browser_init:2:120652
at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:138:5)
回避するため、type
プロパティを削除します。
{
"name": "nuxt-app",
"private": true,
- "type": "module",
"main": "dist-electron/main.js",
"version": "0.0.0",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"nuxt": "3.6.5",
"vue": "^3.4.27",
"vue-router": "^4.3.2"
},
"devDependencies": {
"electron": "^30.0.9",
"electron-builder": "^25.0.0-alpha.9",
"nuxt-electron": "^0.7.0",
"vite-plugin-electron": "^0.28.7",
"vite-plugin-electron-renderer": "^0.14.5"
}
}
3. ビルド用コマンドを追加
Electronアプリケーションをビルドするためのスクリプトコマンドを追加します。
Nuxtアプリケーションをビルドした後、electron-builder
を実行します。
{
"name": "nuxt-app",
"private": true,
"type": "module",
"main": "dist-electron/main.js",
"version": "0.0.0",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
+ "build:win": "nuxt build --prerender && electron-builder --win",
+ "build:mac": "nuxt build --prerender && electron-builder --mac",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"nuxt": "3.6.5",
"vue": "^3.4.27",
"vue-router": "^4.3.2"
},
"devDependencies": {
"electron": "^30.0.9",
"electron-builder": "^25.0.0-alpha.9",
"nuxt-electron": "^0.7.0",
"vite-plugin-electron": "^0.28.7",
"vite-plugin-electron-renderer": "^0.14.5"
}
}
そのほかのビルドオプションは以下を参照してください。
electron-builder.json5
を作成し、ビルド設定を記述する
electron-builder.json5
を作成し、ビルド後のアプリケーションの状態についての設定を記述します。
nuxt-electronのquick-startを踏襲し、json5
形式を採用しています。
そのほかに利用可能なフォーマットは、electron-builder > Common Configurationを参照してください。
// @see - https://www.electron.build/configuration/configuration
{
"$schema": "https://raw.githubusercontent.com/electron-userland/electron-builder/master/packages/app-builder-lib/scheme.json",
"appId": "your.app.id",
"directories": {
"output": "release/${version}"
},
"files": [
".output/**/*",
"dist-electron"
],
"mac": {
"target": [
"dmg"
]
},
"win": {
"target": [
{
"target": "nsis",
"arch": [
"x64"
]
}
],
},
}
そのほかの設定については以下のリファレンスを参照してください。
もう少し易しいドキュメントとして、electron-vite
のドキュメントも参考になります。
ビルドを実行する
npm run build:win
またはnpm run build:mac
を実行してビルドを行ってください。
release/{バージョン}
フォルダにElectronのビルド成果物が格納されています。
Electronを一時的に無効化するには
ブラウザの画面で動作確認を行いたい場合、nuxt.config.ts
のmodulesからnuxt-electron
を削除することで無効化できます。
また、併せてelectron
プロパティを削除することをお勧めします。
4. electronの型情報をNuxtに追加でも触れたとおり、nuxt-electron
がmodulesから削除されることで型情報が変化し、electron
プロパティに型エラーが発生するためです。
一時的な無効化の場合、削除に代わりコメントアウトで対応するのが一般的です。
これらを反映すると、nuxt.config.ts
は以下のようなコードになります。
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: false },
modules: [
// "nuxt-electron"
],
// electron: {
// build: [
// {
// entry: "electron/main.ts",
// },
// ],
// },
});
※modules
プロパティの配列に含まれる要素がnuxt-electron
のみの場合はmodules
プロパティごと削除しても問題ありません。
Discussion
nuxt-electronの記事、すごく参考になりました。
実際に試してみて、Windows環境での問題(おそらくWindows11依存)がありました。
issueで上がってますが、globalにインストールすれば動くとコメントにありましたが動きませんでした。なのでバージョンをさせてビルドすると以下の問題発生。
winCodeSignのdylibを解凍時に管理者権限がないとコピーできずにエラーになる問題のためエラーになります。解決方法としては、winCodeSign.7zwinCodeSign-2.6.0を別途ダウンロードして管理者権限で起動した7-zipで解凍してwinCodeSign-2.6.0フォルダを
C:\Users<YourUserName>\AppData\Local\electron-builder\Cache\winCodeSign\
electron-builderのキャッシュフォルダにコピーする方法で起動できました。
参照先
electron-builderがv25の正式版が出れば解消されると思うのですが、nuxt-electronと関係のないところで躓く罠だったので、参考になればと思いコメントさせていただきます。