3

I'm creating an Electron / Vue application, and I cannot get the Vue Devtools to load in the Electron app window. This is my first time using Electron with Vue, and I'm not sure if there's a dependency issue that I'm not aware of.

I came across this Github issue, but my versions of Electron and vue-cli-plugin-electron are higher, and already include the updated code that is being discussed.

I also tried the following snippet (from here):

win.loadURL(process.env.WEBPACK_DEV_SERVER_URL).then(() => {
  if (!process.env.IS_TEST) {
    setTimeout(() => win.webContents.openDevTools(), 5555)
  }
})

That caused everything to break.

The last major thing I tried was to use vue invoke electron-builder to reinvoke the generator, which was suggested in the docs

However the problem still persists. Can someone take a look at my setup and let me know if there's something obviously wrong?

Here is part of my package.json:

  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "dev": "npm run electron:serve",
    "electron:build": "vue-cli-service electron:build",
    "electron:serve": "vue-cli-service electron:serve",
    "postinstall": "electron-builder install-app-deps",
    "postuninstall": "electron-builder install-app-deps",
    "start": "electron ."
  },
  "main": "background.js",
  "dependencies": {
    "@tailwindcss/postcss7-compat": "^2.0.2",
    "autoprefixer": "^9",
    "bcryptjs": "^2.4.3",
    "core-js": "^3.6.5",
    "electron": "^12.0.5",
    "jsstore": "^3.13.6",
    "postcss": "^7",
    "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.0.2",
    "vue": "^3.0.0",
    "vue-router": "^4.0.0-0",
    "vuex": "^4.0.0-0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "^4.5.12",
    "@vue/cli-plugin-vuex": "^4.5.12",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0",
    "@vue/eslint-config-prettier": "^6.0.0",
    "babel-eslint": "^10.1.0",
    "electron": "^11.0.0",
    "electron-devtools-installer": "^3.2.0",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.3.1",
    "eslint-plugin-vue": "^7.0.0",
    "prettier": "^2.2.1",
    "vue-cli-plugin-electron-builder": "~2.0.0-rc.6",
    "vue-cli-plugin-tailwind": "~2.0.6"
  }

And here is my background.js file:

"use strict";

import { app, protocol, BrowserWindow } from "electron";
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer";
const isDevelopment = process.env.NODE_ENV !== "production";

let win;
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
  { scheme: "app", privileges: { secure: true, standard: true } },
]);

function createWindow() {
  // Create the browser window.
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      // Use pluginOptions.nodeIntegration, leave this alone
      // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
      nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
    },
  });

  if (process.env.WEBPACK_DEV_SERVER_URL) {
    // Load the url of the dev server if in development mode
    win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
    if (!process.env.IS_TEST) win.webContents.openDevTools();
  } else {
    createProtocol("app");
    // Load the index.html when not in development
    win.loadURL("app://./index.html");
  }
}

// Quit when all windows are closed.
app.on("window-all-closed", () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== "darwin") {
    app.quit();
  }
});

app.on("activate", () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) createWindow();
});

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", async () => {
  if (isDevelopment && !process.env.IS_TEST) {
    // Install Vue Devtools
    try {
      await installExtension(VUEJS_DEVTOOLS);
    } catch (e) {
      console.error("Vue Devtools failed to install:", e.toString());
    }
  }
  createWindow();
});

// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
  if (process.platform === "win32") {
    process.on("message", (data) => {
      if (data === "graceful-exit") {
        app.quit();
      }
    });
  } else {
    process.on("SIGTERM", () => {
      app.quit();
    });
  }
}

2 Answers 2

3

The production version of Vue DevTools doesn't support Vue 3 yet.

In order to workaround this issue, you must install the Vue DevTools Beta instead.

Replace this:

await installExtension(VUEJS_DEVTOOLS);

With this:

await installExtension({
  id: 'ljjemllljcmogpfapbkkighbhhppjdbg',
  electron: '>=1.2.1'
})

See the discussion here.

UPDATE

You can now also just use the VUEJS3_DEVTOOLS constant like so:

await installExtension(VUEJS3_DEVTOOLS);
Sign up to request clarification or add additional context in comments.

3 Comments

It is enough to just change it to VUEJS3_DEVTOOLS. No need for id.
I guess that at the time I found this solution there hasn't a preset constant for Vue Devtools Beta :)
At this time, VUEJS3_DEVTOOLS is no longer working for me unless the extension has already been cached by electron. The preset points to an extension ID that is no longer available. I can now use the VUEJS_DEVTOOLS preset extension with Vue.js v3.
1

Don't use timeouts, wait for the dom-ready event instead. I imagine setting it up like this will get everything to work.

Related fix for Redux devtools.

const {
    app,
    BrowserWindow,
} = require("electron");
const {
    default: installExtension,
    VUEJS_DEVTOOLS
} = require("electron-devtools-installer");
const isDev = process.env.NODE_ENV === "development";

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;

async function createWindow() {

    // Create the browser window.
    win = new BrowserWindow({
        width: 800,
        height: 600,
        title: "MyAppTitle",
        webPreferences: {
            devTools: isDev
        }
    });

    // Load app
    win.loadURL("index.html");

    // Only do these things when in development
    if (isDev) {

        // Errors are thrown if the dev tools are opened
        // before the DOM is ready
        win.webContents.once("dom-ready", async () => {
            await installExtension([VUEJS_DEVTOOLS])
                .then((name) => console.log(`Added Extension:  ${name}`))
                .catch((err) => console.log("An error occurred: ", err))
                .finally(() => {
                    win.webContents.openDevTools();
                });
        });
    }

    // Emitted when the window is closed.
    win.on("closed", () => {
        // Dereference the window object, usually you would store windows
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        win = null;
    });
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", createWindow);

// Quit when all windows are closed.
app.on("window-all-closed", () => {
    // On macOS it is common for applications and their menu bar
    // to stay active until the user quits explicitly with Cmd + Q
    if (process.platform !== "darwin") {
        app.quit();
    }
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.