Vue CLI with electron - Unexpected character (1:0) when using native modules

Viewed 419

In some popular NodeJS libraries, e.g. ssh2 or node-pty, there is natively compiled code as part of the library. Creating the project with

vue create my-project
vue add electron-builder
yarn add ssh2

then importing and using ssh2's Client in the background process results in following errors during electron:build

ERROR  Failed to compile with 1 errors                                                                                                                                        5:29:10 PM

 error  in ./node_modules/cpu-features/build/Release/cpufeatures.node

Module parse failed: Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)

 @ ./node_modules/cpu-features/lib/index.js 1:16-60
 @ ./node_modules/ssh2/lib/protocol/constants.js
 @ ./node_modules/ssh2/lib/client.js
 @ ./node_modules/ssh2/lib/index.js
 ...

This error occurs with many other libs or transitive dependencies and the reason for it is absence of native-ext-loader on Webpack chain. I understand why it is not included by default, and I would like to see what is the best way to add it.

1 Answers

One solution I found is this:

  1. Add yarn add -D native-ext-loader (my version is 2.3.0 and electron is at 13.x)
  2. Adjust vue.config.js and add the chainWebpackMainProcess like this:
const path = require('path')
module.exports = {
  pluginOptions: {
    electronBuilder: {
      builderOptions: {
        // options placed here will be merged with default
        mac: {
          target: 'dmg',
          icon: 'build/icon.icns',
          asar: true
        }
      },
      preload: 'src/preload.ts',
      chainWebpackMainProcess(config) {
        config.module
          .rule("node")
          .test(/\.node$/)
          .use("native-ext-loader")
          .loader("native-ext-loader")
          .options(
            process.env.NODE_ENV === "development"
              ? {
                rewritePath: path.resolve(__dirname, "native"),
              }
              : {}
          )
      }
    }
  }
}

Both, electron:build and electron:serve are now working and ssh2 client is happily delivering the stdout to renderer via ipcMain. Not sure it is the most elegant way of solving it, though.

Related