🍥
最新のNuxtでnuxt-electronの無限リロードを回避する
はじめに
nuxt-electronには、v0.7.0
にて「Devモードで起動した場合に無限リロードが発生する」というバグが混入しています。
回避策のひとつとしてNuxtのバージョンをv3.6.5
までダウングレードするというものがありますが、最新のNuxtでも利用できるよう、暫定的に対応する方法を提案します。
既にこの不具合に対応したPRが存在するため、node_modulesを直接編集しこの変更を直接取り込むことで対応します。
※不具合の解消が確認できましたらその旨を追記する予定です。
不具合の詳細
件の不具合はnuxt-electronのIssuesに起票されています。
Issuesの内容を要約します。
- Nuxtアプリケーションにnuxt-electronを追加すると、ElectronブラウザのNuxtが常に再起動し続け、ターミナルとブラウザコンソールに大量のエラーが表示される
- nuxt-electronのフック内で起動ポートがランダムポートになってしまっており、これが無限ループに陥る原因である
また、起動オプションに--no-fork
を追加することも提案されていますが、別のエラーが発生し、動作が不安定でした。
対応する
node_modules/nuxt-electron/dist/index.mjs
, index.cjs
を以下のように編集します。
以下のdiffはindex.mjs
のものです。index.cjs
にも対応する箇所(全く同じコード)があるため、同様に編集してください。
index.mjs
import { defineNuxtModule } from "@nuxt/kit";
import { startup, build } from "vite-plugin-electron";
let options;
let nuxt;
let viteConfigResolve;
const viteConfigPromise = new Promise((resolve) => viteConfigResolve = resolve);
let viteServerResolve;
const viteServerPromise = new Promise((resolve) => viteServerResolve = resolve);
const index = defineNuxtModule({
meta: {
name: "nuxt-electron",
configKey: "electron",
compatibility: {
nuxt: ">=3.0.0"
}
},
hooks: {
async "vite:extendConfig"(viteInlineConfig) {
viteInlineConfig.plugins ?? (viteInlineConfig.plugins = []);
viteInlineConfig.plugins.push({
name: "get-vite-config",
configResolved(config) {
viteConfigResolve(config);
}
});
if (options.renderer) {
viteInlineConfig.plugins.push((await import("vite-plugin-electron-renderer")).default(options.renderer));
}
},
"vite:serverCreated"(server) {
viteServerResolve(server);
},
// For development
listen(server, listener) {
- (async function _listen() {
+ async function _listen() {
var _a, _b, _c, _d;
const addressInfo = server.address();
Object.assign(process.env, {
// This is required, and it is used in Electron-Main.
VITE_DEV_SERVER_URL: `http://localhost:${addressInfo.port}`
});
for (const config of options.build) {
config.vite ?? (config.vite = {});
(_a = config.vite).mode ?? (_a.mode = (await viteConfigPromise).mode);
(_b = config.vite).build ?? (_b.build = {});
(_c = config.vite.build).watch ?? (_c.watch = {});
(_d = config.vite).plugins ?? (_d.plugins = []);
config.vite.plugins.push({
name: "nuxt-electron:startup",
closeBundle() {
if (config.onstart) {
config.onstart.call(this, {
startup,
reload() {
viteServerPromise.then((server2) => server2.ws.send({ type: "full-reload" }));
}
});
} else {
startup();
}
}
});
build(config);
}
- })();
+ }
+ // Setup a 5 seconds delay to avoid error 404 or 500.
+ setTimeout(
+ () => {
+ _listen();
+ },
+ 5000
+ );
},
// For build
async "build:done"() {
var _a;
if (!nuxt.options.dev) {
for (const config of options.build) {
config.vite ?? (config.vite = {});
(_a = config.vite).mode ?? (_a.mode = (await viteConfigPromise).mode);
await build(config);
}
}
},
"build:manifest"(manifest) {
for (const key in manifest) {
manifest[key].dynamicImports = [];
}
}
},
async setup(_options, _nuxt) {
options = _options;
nuxt = _nuxt;
adaptElectronConfig(options, nuxt);
}
});
function adaptElectronConfig(options2, nuxt2) {
var _a, _b, _c;
if (!options2.disableDefaultOptions) {
nuxt2.options.ssr = false;
- nuxt2.options.app.baseURL = "./";
nuxt2.options.app.buildAssetsDir = "/";
nuxt2.options.runtimeConfig.app.baseURL = "./";
nuxt2.options.runtimeConfig.app.buildAssetsDir = "/";
if (!nuxt2.options.dev) {
(_a = nuxt2.options.nitro).runtimeConfig ?? (_a.runtimeConfig = {});
(_b = nuxt2.options.nitro.runtimeConfig).app ?? (_b.app = {});
nuxt2.options.nitro.runtimeConfig.app.baseURL = "./";
}
(_c = nuxt2.options.router.options).hashMode ?? (_c.hashMode = true);
}
}
export {
index as default
};
動作確認
npm run dev
正しく変更ができている場合、Devモードで正常に起動します。
Discussion