3

I'm setting up a test project with Quasar, Electron, and serialport. When starting the application with a minimal serialport test, I get the following error:

vue-router.esm.js?85f8:2128 TypeError: Cannot read property 'indexOf' of undefined
    at Function.getFileName (bindings.js?d8c5:178)
    at bindings (bindings.js?d8c5:82)
    at eval (win32.js?0965:1)
    at Object../node_modules/@serialport/bindings/lib/win32.js (vendor.js:340)
    at __webpack_require__ (app.js:854)
    at fn (app.js:151)
    at eval (index.js?3983:6)
    at Object../node_modules/@serialport/bindings/lib/index.js (vendor.js:252)
    at __webpack_require__ (app.js:854)
    at fn (app.js:151)

The error even happens when I only include the serialport package without doing any more. It seems to be a basic problem. Code to reproduce the problem:

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
import SerialPort from 'serialport';

@Component
export default class Index extends Vue {
  test() {
    console.log('test', SerialPort);
  }
}
</script>

I tried everything I could find here, in the Quasar forum, etc. pp.: electron-rebuild, trying to config serialport as an external dependency, ...

I'm not quite sure if the rebuild process is working as expected, but I don't know what to check to make sure it does. The electron example project with serialport is working for me. Maybe it is a Quasar related thing?

Can I get more information on the rebuild process? I tried different combinations with specifying the version, but nothing is helping.

enter image description here

I also asked this question as an issue in the serialport repository, but adding it in the vue.config.js doesn't work, because I'm using Quasar as the CLI option.

enter image description here

I think the main problem is how to rebuild serialport properly for electron when Quasar is in place, which seems to be not working as expected.

Fabian Deitelhoff
  • 712
  • 1
  • 7
  • 23

4 Answers4

8

I also had quite some trouble getting Serialport to run in Quasar and Electron, but I got it to work. The solution is not really pretty and might break in the future.

As you wrote, you need to run electron-rebuild. You can execute it by running "./node_modules/.bin/electron-rebuild". You should also put in in your package .json in the "scripts" section

"install": "electron-rebuild"

I used the Electron preload script to put serialport in the window object. Here is the documentation on how to enable this. In the electron-main.js, you also need to add the following line

app.allowRendererProcessReuse = false;

If missing, electron will fail to load.

In electron-preload.js, put this

window.serialport = require("serialport");

You can now use serialport in your Quasar project by using window.serialport.

Another problem I encountered was the fact that Quasar changes the package.json while packaging the project and removes the install script so electron-rebuild does not run while building and the packed version does not work. I managed to fix this by adding a "beforePackaging" Hook into the electron part of quasar.conf.js

//Top of the file
const path = require("path");
const crossSpawn = require("cross-spawn");
...
electron: {
  ...
  beforePackaging(params) {
    return new Promise(resolve => {
      const runner = crossSpawn(
        path.join("node_modules", ".bin", "electron-rebuild"),
        [""],
        {
          stdio: "inherit",
          stdout: "inherit",
          stderr: "inherit",
          cwd: params.unpackagedDir
        }
      );

      runner.on("close", () => {
        resolve();
      });
    });
  },
}

Maybe somebody has a nicer solution to this, but I hope, this helps.

  • Many thanks. Your suggestion is working. It is a dirty hack, I think. But at least a working one. :) I still have problems with the rebuild because it doesn't work automatically. But it is working manually, so I will use it as it is for now. – Fabian Deitelhoff Jul 28 '20 at 21:15
  • Thank you!!! I spent all afternoon trying to figure this out. Your answer is the only thing that worked. – mattdedek Aug 11 '20 at 23:07
  • 1
    After some further development and testing, I encounter the following problem: electron-builder is fording the electron-rebuild in the devDependencies section. If I move the package to this location, the beforePackaging function cannot find the node_modules/.bin/electron-rebuild path. Maybe because only non-dev dependencies are installed? Is there a solution/workaround for this problem? – Fabian Deitelhoff Aug 21 '20 at 18:57
  • I would like to let future readers know that this awesome answer also works for [node-hid](https://github.com/node-hid/node-hid) with a minor detail: add `cfg.externals = { "node-hid": 'commonjs node-hid' }` in `quasar.conf.js` > `electron` > `extendWebpack(cfg)`. The rest is the exact same thing except that you should type `node-hid` instead of `serialport`. But it works perfectly. I spent hours trying to fix this so I hope it helps someone. – Zeke Jan 11 '21 at 23:23
1
beforePackaging (params) {
    return new Promise(resolve => {
      const runner = crossSpawn(
        '..\\..\\..\\node_modules\\.bin\\electron-rebuild -f -v 9.3.1 -w serialport',
        [''],
        {
          stdio: 'inherit',
          stdout: 'inherit',
          stderr: 'inherit',
          cwd: params.unpackagedDir
        }
      )
      runner.on('close', () => {
        resolve()
      })
    })
  },
Jun Mao
  • 11
  • 1
  • Code dumps do not make for good answers. You should explain *how* and *why* this solves their problem. I recommend reading, "[How do I write a good answer?"](//stackoverflow.com/help/how-to-answer). This can help future users learn and eventually apply that knowledge to their own code. You are also likely to have positive feedback/upvotes from users, when the code is explained. – John Conde Mar 02 '21 at 00:46
0
   beforePackaging(params) {
        return new Promise((resolve) => {
          const runner = crossSpawn(
           "npx electron-rebuild", [""], {
              stdio: "inherit",
              stdout: "inherit",
              stderr: "inherit",
              cwd: params.unpackagedDir,
            }
          );
          runner.on("close", () => resolve());
        });
      }
dokodream
  • 1
  • 1
0

When you packaging and building whole project,You can use electron-preload.js to put serialport in the window project.

window.serialport = require("serialport");

Then You can now use

const SerialPort = window.serialport.SerialPort;